Skip to content

Commit

Permalink
add hook for default base aspect applied to all aspects
Browse files Browse the repository at this point in the history
  • Loading branch information
schosin committed Jun 3, 2020
1 parent be6a5c9 commit fd62281
Show file tree
Hide file tree
Showing 14 changed files with 786 additions and 66 deletions.
45 changes: 39 additions & 6 deletions artemis-core/artemis/src/main/java/com/artemis/Aspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -206,14 +206,29 @@ public static Aspect.Builder one(Class<? extends Component>... types) {
public static Aspect.Builder one(Collection<Class<? extends Component>> types) {
return new Builder().one(types);
}

/**
* Changes whether the default aspect will be applied to this aspect
* when used for a subscription.
*
* @param defaults
* whether to apply default aspect
*
* @return an aspect that will have the default aspect applied to it
* depending on the value.
*/
public static Builder defaults(boolean defaults) {
return new Builder().defaults(defaults);
}

/**
* Constructs instances of {@link Aspect}.
*/
public static class Builder {
private final Bag<Class<? extends Component>> allTypes;
private final Bag<Class<? extends Component>> exclusionTypes;
private final Bag<Class<? extends Component>> oneTypes;
final Bag<Class<? extends Component>> allTypes;
final Bag<Class<? extends Component>> exclusionTypes;
final Bag<Class<? extends Component>> oneTypes;
boolean defaults = true;

private Builder() {
allTypes = new Bag<Class<? extends Component>>();
Expand Down Expand Up @@ -246,6 +261,7 @@ public Builder copy() {
b.allTypes.addAll(allTypes);
b.exclusionTypes.addAll(exclusionTypes);
b.oneTypes.addAll(oneTypes);
b.defaults = defaults;
return b;
}

Expand All @@ -258,7 +274,7 @@ public Builder copy() {
*
* @return an aspect that can be matched against entities
*/
public Builder all(Collection<Class<? extends Component>> types) {
public Builder all(Iterable<Class<? extends Component>> types) {
for (Class<? extends Component> t : types) {
allTypes.add(t);
}
Expand Down Expand Up @@ -292,7 +308,7 @@ public final Builder one(Class<? extends Component>... types) {
*
* @return an aspect that can be matched against entities
*/
public Builder one(Collection<Class<? extends Component>> types) {
public Builder one(Iterable<Class<? extends Component>> types) {
for (Class<? extends Component> t : types)
oneTypes.add(t);

Expand Down Expand Up @@ -332,12 +348,28 @@ public final Builder exclude(Class<? extends Component>... types) {
*
* @return an aspect that can be matched against entities
*/
public Builder exclude(Collection<Class<? extends Component>> types) {
public Builder exclude(Iterable<Class<? extends Component>> types) {
for (Class<? extends Component> t : types)
exclusionTypes.add(t);

return this;
}

/**
* Changes whether the default aspect will be applied to this aspect
* when used for a subscription.
*
* @param defaults
* whether to apply default aspect
*
* @return an aspect that will have the default aspect applied to it
* depending on the value.
*/
public Builder defaults(boolean defaults) {
this.defaults = defaults;

return this;
}

/**
* Bake an aspect.
Expand Down Expand Up @@ -391,6 +423,7 @@ public String toString() {
"all=" + append(allTypes) +
", one=" + append(oneTypes) +
", exclude=" + append(exclusionTypes) +
", defaults=" + defaults +
']';
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public class AspectSubscriptionManager extends BaseSystem {

private final IntBag changed = new IntBag();
private final IntBag deleted = new IntBag();

private Aspect.Builder defaultAspect;
private final Bag<Class<? extends Component>> tmpComponentBag = new Bag<>();

protected AspectSubscriptionManager() {
subscriptionMap = new HashMap<Aspect.Builder, EntitySubscription>();
Expand All @@ -41,7 +44,26 @@ protected void setWorld(World world) {
super.setWorld(world);

// making sure the first subscription matches all entities
get(all());
get(all().defaults(false));
}

/**
* <p>Gets the entity subscription for the {@link Aspect}.
* Subscriptions are only created once per aspect.</p>
*
* Be careful when calling this within {@link BaseSystem#processSystem()}.
* If the subscription does not exist yet, the newly created subscription
* will reflect all the chances made by the currently processing system,
* NOT the state before the system started processing. This might cause
* the system to behave differently when run the first time (as
* subsequent calls won't have this issue).
* See https://github.com/junkdog/artemis-odb/issues/551
*
* @param builder Aspect to match.
* @return {@link EntitySubscription} for aspect.
*/
public EntitySubscription get(Aspect.Builder builder) {
return get(builder, true);
}

/**
Expand All @@ -57,12 +79,42 @@ protected void setWorld(World world) {
* See https://github.com/junkdog/artemis-odb/issues/551
*
* @param builder Aspect to match.
* @param applyDefaults whether to apply default aspect
* @return {@link EntitySubscription} for aspect.
*/
public EntitySubscription get(Aspect.Builder builder) {
EntitySubscription get(Aspect.Builder builder, boolean applyDefaults) {
if (applyDefaults && defaultAspect != null && builder.defaults) {
builder = applyDefaultAspect(builder.copy());
}

EntitySubscription subscription = subscriptionMap.get(builder);
return (subscription != null) ? subscription : createSubscription(builder);
}

private Aspect.Builder applyDefaultAspect(Aspect.Builder builder) {
tmpComponentBag.clear();
tmpComponentBag.addAll(defaultAspect.allTypes);
tmpComponentBag.removeAll(builder.allTypes);
tmpComponentBag.removeAll(builder.oneTypes);
tmpComponentBag.removeAll(builder.exclusionTypes);
builder.all(tmpComponentBag);

tmpComponentBag.clear();
tmpComponentBag.addAll(defaultAspect.oneTypes);
tmpComponentBag.removeAll(builder.allTypes);
tmpComponentBag.removeAll(builder.oneTypes);
tmpComponentBag.removeAll(builder.exclusionTypes);
builder.one(tmpComponentBag);

tmpComponentBag.clear();
tmpComponentBag.addAll(defaultAspect.exclusionTypes);
tmpComponentBag.removeAll(builder.allTypes);
tmpComponentBag.removeAll(builder.oneTypes);
tmpComponentBag.removeAll(builder.exclusionTypes);
builder.exclude(tmpComponentBag);

return builder;
}

private EntitySubscription createSubscription(Aspect.Builder builder) {
EntitySubscription entitySubscription = new EntitySubscription(world, builder);
Expand Down Expand Up @@ -120,4 +172,8 @@ void processComponentIdentity(int id, BitVector componentBits) {
public ImmutableBag<EntitySubscription> getSubscriptions() {
return subscriptions;
}

void setDefaultAspect(Aspect.Builder aspect) {
this.defaultAspect = aspect;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public final class EntityTransmuter {
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());
}

EntityTransmuter(World world, Aspect aspect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public final class WorldConfiguration {

private boolean alwaysDelayComponentRemoval = false;
private Set<Class<? extends BaseSystem>> registered = new HashSet<Class<? extends BaseSystem>>();

private Aspect.Builder defaultAspect;

public WorldConfiguration() {
// reserving space for core managers
systems.add(null); // ComponentManager
Expand Down Expand Up @@ -161,7 +162,9 @@ void initialize(World world, Injector injector, AspectSubscriptionManager asm) {
invocationStrategy.setWorld(world);

world.invocationStrategy = invocationStrategy;


asm.setDefaultAspect(defaultAspect);

systems.set(COMPONENT_MANAGER_IDX, world.getComponentManager());
systems.set(ENTITY_MANAGER_IDX, world.getEntityManager());
systems.set(ASPECT_SUBSCRIPTION_MANAGER_IDX, asm);
Expand Down Expand Up @@ -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.
*
* @param aspect default aspect
* @return this
*/
public WorldConfiguration setDefaultAspect(Aspect.Builder aspect) {
this.defaultAspect = aspect;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class WorldConfigurationBuilder {
private ArtemisPlugin activePlugin;
private final InjectionCache cache;
private SystemInvocationStrategy invocationStrategy;
private Aspect.Builder defaultAspect;

public WorldConfigurationBuilder() {
reset();
Expand All @@ -46,6 +47,7 @@ public WorldConfiguration build() {
registerFieldResolvers(config);
registerInvocationStrategies(config);
config.setAlwaysDelayComponentRemoval(alwaysDelayComponentRemoval);
config.setDefaultAspect(defaultAspect);
reset();
return config;
}
Expand Down Expand Up @@ -266,6 +268,17 @@ public WorldConfigurationBuilder with(ArtemisPlugin... plugins) {
addPlugins(plugins);
return this;
}

/**
* Sets the default aspect to be applied to all aspects when used for a subscription.
*
* @param aspect default aspect
* @return this
*/
public WorldConfigurationBuilder defaultAspect(Aspect.Builder aspect) {
this.defaultAspect = aspect;
return this;
}

/**
* helper to queue systems for registration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,9 @@
* @return excluding types
*/
Class<? extends Component>[] exclude() default {};

/**
* @return whether to apply default aspect when used for a subscription
*/
boolean defaults() default true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,9 @@
*/
Class<? extends Component>[] value() default {};

/**
* @return whether to exclude default aspect when used for a subscription
*/
boolean excludeDefaults() default false;

}
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,14 @@ private AspectDescriptor descriptor(Field field) {
}

private Aspect.Builder toAspect(AspectDescriptor ad) {
return all(ad.all()).one(ad.one()).exclude(ad.exclude());
return all(ad.all()).one(ad.one()).exclude(ad.exclude()).defaults(ad.defaults());
}

private Aspect.Builder toAspect(All all, One one, Exclude exclude) {
return all(all != null ? all.value() : EMPTY_COMPONENT_CLASS_ARRAY)
.one(one != null ? one.value() : EMPTY_COMPONENT_CLASS_ARRAY)
.exclude(exclude != null ? exclude.value() : EMPTY_COMPONENT_CLASS_ARRAY);
.exclude(exclude != null ? exclude.value() : EMPTY_COMPONENT_CLASS_ARRAY)
.defaults(exclude == null || !exclude.excludeDefaults());
}

private Class<? extends Component>[] allComponents(Field field) {
Expand Down
Loading

0 comments on commit fd62281

Please sign in to comment.