GitBrincie212 / Apel-Mod

Apel is a library that brings particle animations to the table with flexible behaviour and a clean developer interface. It promises also lots of predefined shapes & paths to help the developer on their particle scene
Other
2 stars 1 forks source link

Standardize ParticleObject and ParticleCombiner #3

Closed DarthSharkie closed 3 months ago

DarthSharkie commented 3 months ago

The previous implementation needed to allocate an InterceptData and InterceptResult for before and after interceptors. Switching to DrawContext and its subclasses allows for allocating a single object per before/after interceptor, strongly-typed contextual values, and fewer generics to manage.

Note: There's no strong reason for the DrawContext objects to be inner classes, but it makes the most sense to me organizationally, lest we wind up with twice as many DrawContext classes and subclasses as ParticleObjects. It's possible that some can be reused, but they're simple enough that I don't see that as a problem right now. While the ParticleCombiner's AfterChildDrawContext class makes no extension to the DrawContext, it does provide a durable type for that interceptor function to use if there are future properties added that are specific to afterDrawChild in the ParticleCombiner.

Assuming this is agreeable, I'll follow up with another PR to move each of the ParticleObject subclasses to this approach.

DarthSharkie commented 3 months ago

Here's an example of how it looks from the dev/user perspective (for the ParticleCombiner):

    @Override
    public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
        if (world.isClient) return TypedActionResult.pass(user.getMainHandStack());
        animators((ServerWorld) world, user);
        return TypedActionResult.pass(user.getMainHandStack());
    }

    private void animators(ServerWorld world, PlayerEntity user) {
        ParticleSphere sphere = new ParticleSphere(ParticleTypes.END_ROD, 2f, 500);
        List<ParticleCircle> circles = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ParticleCircle circle = new ParticleCircle(ParticleTypes.DRAGON_BREATH, 3f, 500);
            int finalI = i;
            circle.beforeCalcsIntercept = (InterceptData<ParticleCircle.beforeCalc> data, ParticleCircle obj) -> {
                obj.radius += 0.01f * finalI;
                obj.setRotation(obj.getRotation().add(0.001f * finalI, 0, 0));
                return new InterceptedResult<>(data, obj);
            };
            circles.add(circle);
        }
        ParticleCombiner<ParticleCircle> circleCombiner = new ParticleCombiner<>(circles);
        ParticleCombiner<?> combinedObj = new ParticleCombiner<>(sphere, circleCombiner);
        combinedObj.setBeforeChildDrawIntercept((context) -> {
            context.getChildObject().setRotation(context.getChildObject().getRotation().add(0, 0.01f, 0));
            context.setShouldDraw(context.getStep() / 20 % 5 != 0);
            context.setDrawPosition(context.getDrawPosition().add(0, (float) (context.getStep() * 5) / 1000, 0));
            return context;
        });

        PointAnimator pointAnimator = new PointAnimator(1, combinedObj, user.getPos().toVector3f().add(5, 5, 5), 1000);
        pointAnimator.beginAnimation(world);
    }
DarthSharkie commented 3 months ago

I'll plan to go back and separate the standardizing from the DrawInterceptor -> DrawContext change on this one. This PR will have the standardizing, and I'll submit a separate one with the DrawContext so we can debate that change there.

Hopefully get to this later tonight...

DarthSharkie commented 3 months ago

OK, this is back to a clean InterceptorData and InterceptorResult state now.