-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #371: add hook for default base aspect applied to all aspects #596
base: develop
Are you sure you want to change the base?
Conversation
Somehow I broke the GWT tests, didn't know about the gwttest maven profile. I don't have any experience with GWT, but I'll see what I can do. |
👋 @junkdog |
Thanks for the PR! Sorry for letting it sit so long. |
I can fix the conflict. Would you rather see a merge or rebase? Regarding the code review, there is already some discussion in #371. Regarding performance, I wasn't able to get the benchmarks to run on my system, so I never provided any. |
Performance is probably not an issue, nobody should have aspect creation in a tight loop post init. |
Leave it, the conflict is so minor we can fix it on merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the code is sound I think the API needs some work before we can consider merging.
Just thinking out loud, let me know what your thoughts are:
- This is a power user feature so ideally we keep the core API the same for basic users.
- I'd favor a little more verbosity at aspect annotation sites just to make it obvious the default aspect is going to be applied;
@One(..) @All(..) @DefaultAspect
(name pending). And if we do that, maybe it makes sense to give the user a little more control /which/ global aspect is applied? - For programmatic Aspects it might make more sense to just have a
Aspect builder Aspect.builder.merge(Globals.DEFAULT)
so the way things work are obvious, flexible and less magical. - The API doesn't document (yet) how odb will combine the global and local aspects and how conflicts are resolved.
artemis-core/artemis/src/main/java/com/artemis/AspectSubscriptionManager.java
Show resolved
Hide resolved
artemis-core/artemis/src/main/java/com/artemis/AspectSubscriptionManager.java
Show resolved
Hide resolved
public EntitySubscription get(Aspect.Builder builder) { | ||
EntitySubscription get(Aspect.Builder builder, boolean applyDefaults) { | ||
if (applyDefaults && defaultAspect != null && builder.defaults) { | ||
builder = applyDefaultAspect(builder.copy()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can cache this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we already assumed that most people don't create EntitySubscriptions in tight loops (I'd say mostly in the initialize phase), such a cache would increase the memory usage for every distinct aspect used and only helps for those aspects that are used multiple times.
Personally I think I have more unique aspects in my projects than non-unqiue aspects, so it's wasting memory for marginal improvement in startup time, if any.
artemis-core/artemis/src/main/java/com/artemis/AspectSubscriptionManager.java
Show resolved
Hide resolved
@@ -27,7 +27,7 @@ | |||
private final ShortBag entityToIdentity; | |||
|
|||
public EntityTransmuter(World world, Aspect.Builder aspect) { | |||
this(world, world.getAspectSubscriptionManager().get(aspect).getAspect()); | |||
this(world, world.getAspectSubscriptionManager().get(aspect, false).getAspect()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the original code even obtaining a subscription in the first place? It doesn't even do anything with subscriptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By doing it that way, the aspect goes through ComponentManager#synchronize. Doesn't look like that's necessary for an EntityTransmuter, but not 100% sure. Could be simplified to aspect.build(world). I would still need a way to exclude defaults for this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is for @junkdog.
@@ -222,4 +225,15 @@ public boolean isAlwaysDelayComponentRemoval() { | |||
public void setAlwaysDelayComponentRemoval(boolean value) { | |||
this.alwaysDelayComponentRemoval = value; | |||
} | |||
|
|||
/** | |||
* Sets the default aspect to be applied to all aspects when used for a subscription. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify what 'to be applied' means and how it resolves conflicts. You could potentially end up with aspects with the same component in both exclude or include.
artemis-core/artemis/src/main/java/com/artemis/annotations/AspectDescriptor.java
Show resolved
Hide resolved
Looking at your feedback, I agree that we should consider moving the "exclude default" out of By having such an annotation, Personally I'd prefer moving those flags to a new annotation As for "/which/ global aspect", I would also not implement multiple, selectable global aspects using this default aspect mechanic. If we want something like that, I'd rather say we'll look into something like
|
Brain dump, lemme know what you think.
It's an interesting idea, reconstituting aspects into annotation based types, and it works around the limits of constants in annotations. If they stack the use cases go beyond just global aspects.
It has a lot of potential but the idea needs a bit of polish and integration. Worth talking over with @junkdog. Feels like it could fit 3.0. Only technical blocker is the GWT reflection generator not storing metadata on annotations (it should be doable).
For 2.5 For EntitySystem constructor aspects we can merge the defaults in Users can use We don't do anything magical in subscription manager or anywhere else in the API to keep things predictable; if you make a call with a certain Aspect.Builder you'll get the stuff for that Aspect.Builder. If the default aspect is not set nothing happens, it becomes zero impact for users. No magic or API or behavioral changes. -- Big picture, global aspects still feel a bit kitchen-sinky and edge-casey which is something @junkdog wants to avoid. Can we come up with extension point for an AspectFactory so we could put the impl into a plugin? Edit: changed order a bit. |
In general I would say that Defaults in AspectFieldResolver: Defaults in SystemMetadata: Thoughts on AspectFieldResolver and Aspect: Why is there no case for creating Aspect? Probably not the most used feature, but maybe someone wants a field to check whether an entity matches another aspect using As a side note: We should also not forget about TagManager and GroupManager. Adding "Paused" to an entity should not magically remove it's tag or groups. |
This PR adds the ability to add defaults to every aspect unless explicitly excluding those defaults.
I'm not sure about the best way to disable default aspects for All/One/Excude. For now I added the flag to Exclude, but I'm open for alternatives.
-- Copied from #371
Here's an overview what I've done:
defaults() default true
excludeDefaults() default false
(not sure this is the best way for All/One/Exclude)This should result in no runtime changes for existing applications and a slight overhead for creations of EntitySubscriptions.
I have only worked in the artemis-core/artemis module. All tests are passing, but I'm not certain whether I forgot anything (plugins, serialization, fluid, gwt, ...).