This was briefly discussed on Discord and the boss agreed on a discussion on this.
The current context variable API is
registry.set<Username>("s9w");
const auto &username = registry.ctx<Username>();
Plus .try_ctx<T>() and .unset<T>().
I think the names of these functions is less than optimal for these reasons:
.set() can be easily mistaken as the counterpart to .get(), which it is not..ctx() doesn't make it obvious whether it's a function for setting or for retrieving information.I'm not sure if I have a good replacement. Spontaneously get_ctx and set_ctx come to mind, or even more explicit get_ctx_var and set_ctx_var.
Also I'd like to point out the term context variable does have some linguistic overlap with the term meta context.
Thoughts?
I'd avoid the longest version (*_var) to be honest. A little too long for my tastes. 馃檪
Hi everybody, stumbled upon this thread by accident. The context functions were somewhat confusing to me when I first encountered them. So here's my 2 cents:
Just renaming .set() to .set_ctx() (and .unset() to .unset_ctx()) might be enough. Makes it clear that .ctx() and .set_ctx() are a pair but preserves the terse notation for retrieving context variables.
Another advantage: this naming convention is used in the QT framework for getter/setter pairs. So some C++ developers will be already familiar with it.
Hi, personal opinion in coming:
I think prefixing ctx_ is a good idea, because you know with what you are working.
eg:
.ctx_set()
.ctx_get()
Another option would be to make the context a separate object and have just this:
auto &ctx = registry.context();
The object can expose the same functionalities of the other containers then, like emplace and remove.
It this case, the context becomes something like a handle for an entity that is always there and can have components assigned to it? Even though it's stupid, it gave me an idea of how entity 0 can be used as entt::null almost without wasting space. The almost part, unfortunatelly, suggests that for each context variable there will be a pool with a single instance.
The context is already something like a handle for an entity and so on, but without an entity. 馃槃
Btw go on, now I'm curious to know your idea. 馃憤
Well, the idea is exactly this: the context is an entity. A full-blown entity. You can stamp it to another entity, which can be useful for cloning the registries or having registry prefabs (I don't know for what!). Also, the signals are there more or less for free so that the program can react to context changes (I don't know if there is already such mechanism). And all that would be based on the very same code as the regular entity handling. But I'm sure it's not exactly practical, because the O(1) of entity access may still have more overhead then the current context implementation.
Another option would be to make the context a separate object and have just this:
I just wanted to chime in and say that's a pattern I've used with success in the past. It makes it abundantly clear what's happening and intellisense & co will offer a nice small list of operations for that object. Also it's nice to pass functions that context handler instead of the entire registry. I could imagine you find it a bit too long/verbose though?
No, well, I mean, I proposed it, so I'm definitely in favor. @s9w
@Innokentiy-Alaytsev do you know why we can't implement it as you suggest? Because it's already possible to implement your own context like that and ignore the built-in one. Just reserve entity 0 for the context and that's all.
Thinking about/looking into this issue. What if the context was just an entt::any object rather than a map, a vector or any other data structure?
In this case, the user can decide how to use it. You can just put a single context class defined by the user, a map of entt::any or whatever fits the requirements of your application.
Most helpful comment
Another option would be to make the context a separate object and have just this:
The object can expose the same functionalities of the other containers then, like
emplaceandremove.