Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.zigythebird.playeranimcore.animation.Animation;
import com.zigythebird.playeranimcore.animation.CustomModelBone;
import com.zigythebird.playeranimcore.loading.AnimationLoader;
import com.zigythebird.playeranimcore.loading.KeyFrameLoader;
import com.zigythebird.playeranimcore.loading.UniversalAnimLoader;
import com.zigythebird.playeranimcore.math.Vec3f;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -19,6 +21,8 @@ public class PlayerAnimLib {

public static final Type ANIMATIONS_MAP_TYPE = new TypeToken<Map<String, Animation>>() {}.getType();
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(CustomModelBone.class, new CustomModelBone.Deserializer())
.registerTypeAdapter(Vec3f.class, new Vec3f.Deserializer())
.registerTypeAdapter(Animation.Keyframes.class, new KeyFrameLoader())
.registerTypeAdapter(Animation.class, new AnimationLoader())
.registerTypeAdapter(ANIMATIONS_MAP_TYPE, new UniversalAnimLoader())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import com.zigythebird.playeranimcore.animation.keyframe.event.data.ParticleKeyframeData;
import com.zigythebird.playeranimcore.animation.keyframe.event.data.SoundKeyframeData;
import com.zigythebird.playeranimcore.loading.UniversalAnimLoader;
import com.zigythebird.playeranimcore.math.Vec3f;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand All @@ -44,7 +43,7 @@
* <p>
* Modifications or extensions of a compiled Animation are not supported, and therefore an instance of <code>Animation</code> is considered final and immutable
*/
public record Animation(ExtraAnimationData data, float length, LoopType loopType, Map<String, BoneAnimation> boneAnimations, Keyframes keyFrames, Map<String, Vec3f> bones, Map<String, String> parents) implements Supplier<UUID> {
public record Animation(ExtraAnimationData data, float length, LoopType loopType, Map<String, BoneAnimation> boneAnimations, Keyframes keyFrames, Map<String, CustomModelBone> bones, Map<String, String> parents) implements Supplier<UUID> {
public record Keyframes(SoundKeyframeData[] sounds, ParticleKeyframeData[] particles, CustomInstructionKeyframeData[] customInstructions) {
@Override
public int hashCode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package com.zigythebird.playeranimcore.animation;

import com.google.gson.JsonArray;
import com.zigythebird.playeranimcore.PlayerAnimLib;
import com.zigythebird.playeranimcore.animation.keyframe.*;
import com.zigythebird.playeranimcore.animation.keyframe.event.CustomKeyFrameEvents;
Expand All @@ -39,6 +40,7 @@
import com.zigythebird.playeranimcore.animation.layered.modifier.SpeedModifier;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode;
import com.zigythebird.playeranimcore.bindings.PlatformModel;
import com.zigythebird.playeranimcore.bones.*;
import com.zigythebird.playeranimcore.easing.EasingType;
import com.zigythebird.playeranimcore.enums.PlayState;
Expand Down Expand Up @@ -75,7 +77,7 @@ public abstract class AnimationController implements IAnimation {
protected final Map<String, Vec3f> bonePositions;
protected final Map<String, AdvancedPlayerAnimBone> bones = new Object2ObjectOpenHashMap<>();
protected final Map<String, PlayerAnimBone> activeBones = new Object2ObjectOpenHashMap<>();
protected final Map<String, PivotBone> pivotBones = new Object2ObjectOpenHashMap<>();
protected final Map<String, CustomBone> pivotBones = new Object2ObjectOpenHashMap<>();
protected Queue<QueuedAnimation> animationQueue = new LinkedList<>();
protected final MochaEngine<AnimationController> molangRuntime;

Expand Down Expand Up @@ -739,13 +741,26 @@ else if (pivotBones.containsKey(entry.getKey()))
}

this.pivotBones.clear();
for (Map.Entry<String, Vec3f> entry : currentAnimation.animation().bones().entrySet()) {
this.pivotBones.put(entry.getKey(), new PivotBone(entry.getKey(), entry.getValue()));
for (Map.Entry<String, CustomModelBone> entry : currentAnimation.animation().bones().entrySet()) {
this.pivotBones.put(entry.getKey(), new CustomBone(entry.getKey(), entry.getValue().pivot(), loadCustomModel(
entry.getValue().texture(),
entry.getValue().elements()
)));
}

this.postAnimationSetupConsumer.accept((name) -> bones.getOrDefault(name, null));
}

protected abstract @Nullable PlatformModel loadCustomModel(byte @Nullable [] texture, @Nullable JsonArray elements);

@Override
public void collectModels(Consumer<CustomBone> consumer) {
for (CustomBone customBone : this.pivotBones.values()) {
if (customBone.getModel() == null) continue;
consumer.accept(customBone);
}
}

/**
* Compute animation value for the given keyframes at the specified tick
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.zigythebird.playeranimcore.animation;

import com.google.gson.*;
import com.zigythebird.playeranimcore.math.Vec3f;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Type;
import java.util.Base64;

public record CustomModelBone(Vec3f pivot, byte @Nullable [] texture, @Nullable JsonArray elements) {
public static class Deserializer implements JsonDeserializer<CustomModelBone> {
@Override
public CustomModelBone deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
return new CustomModelBone(
ctx.deserialize(obj.get("pivot"), Vec3f.class),
obj.has("texture") ? Base64.getDecoder().decode(obj.get("texture").getAsString()) : null,
obj.getAsJsonArray("elements")
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@

package com.zigythebird.playeranimcore.animation;

import com.google.gson.JsonArray;
import com.zigythebird.playeranimcore.bindings.PlatformModel;
import com.zigythebird.playeranimcore.bones.PlayerAnimBone;
import com.zigythebird.playeranimcore.math.Vec3f;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import team.unnamed.mocha.MochaEngine;

import java.util.ArrayList;
Expand Down Expand Up @@ -129,4 +132,9 @@ public PlayerAnimBone get3DTransformRaw(@NotNull PlayerAnimBone bone) {
}
return bone;
}

@Override
protected @Nullable PlatformModel loadCustomModel(byte @Nullable [] texture, @Nullable JsonArray elements) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@
import com.zigythebird.playeranimcore.animation.AnimationData;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode;
import com.zigythebird.playeranimcore.bones.CustomBone;
import com.zigythebird.playeranimcore.bones.PlayerAnimBone;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.function.Consumer;

/**
* A container to make swapping animation object easier
* It will clone the behaviour of the held animation
Expand Down Expand Up @@ -94,4 +97,9 @@ public String toString() {
"anim=" + anim +
'}';
}

@Override
public void collectModels(Consumer<CustomBone> consumer) {
if (this.anim != null) this.anim.collectModels(consumer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import com.zigythebird.playeranimcore.animation.AnimationData;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode;
import com.zigythebird.playeranimcore.bones.CustomBone;
import com.zigythebird.playeranimcore.bones.PlayerAnimBone;
import it.unimi.dsi.fastutil.Pair;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
* Player animation stack, can contain multiple active or passive layers, will always be evaluated from the lowest index.
Expand Down Expand Up @@ -131,4 +133,13 @@ public String toString() {
"layers=" + layers +
'}';
}

@Override
public void collectModels(Consumer<CustomBone> consumer) {
for (Pair<Integer, IAnimation> layer : this.layers) {
if (layer.right().isActive()) {
layer.right().collectModels(consumer);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@
import com.zigythebird.playeranimcore.animation.AnimationData;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode;
import com.zigythebird.playeranimcore.bones.CustomBone;
import com.zigythebird.playeranimcore.bones.PlayerAnimBone;
import org.jetbrains.annotations.NotNull;

import java.util.function.Consumer;

public interface IAnimation {
FirstPersonConfiguration DEFAULT_FIRST_PERSON_CONFIG = new FirstPersonConfiguration();

Expand Down Expand Up @@ -88,4 +91,6 @@ default FirstPersonConfiguration getFirstPersonConfiguration() {
default boolean canRemove() {
return false;
}

default void collectModels(Consumer<CustomBone> consumer) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.zigythebird.playeranimcore.animation.layered.modifier.AbstractModifier;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration;
import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode;
import com.zigythebird.playeranimcore.bones.CustomBone;
import com.zigythebird.playeranimcore.bones.PlayerAnimBone;
import com.zigythebird.playeranimcore.easing.EasingType;
import org.jetbrains.annotations.NotNull;
Expand All @@ -14,6 +15,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;


Expand Down Expand Up @@ -41,16 +43,25 @@ public ModifierLayer() {
return animation;
}

protected @Nullable IAnimation getTopAnimation() {
if (!this.modifiers.isEmpty()) {
return this.modifiers.getFirst();
} else if (this.animation != null) {
return this.animation;
} else {
return null;
}
}

@Override
public void tick(AnimationData state) {
for (int i = 0; i < modifiers.size(); i++) {
if (modifiers.get(i).canRemove()) {
removeModifier(i--);
}
}
if (modifiers.size() > 0) {
modifiers.get(0).tick(state);
} else if (animation != null) animation.tick(state);
IAnimation top = getTopAnimation();
if (top != null) top.tick(state);
}

public void addModifier(@NotNull AbstractModifier modifier, int idx) {
Expand Down Expand Up @@ -141,41 +152,34 @@ protected void linkModifiers() {

@Override
public boolean isActive() {
if (!modifiers.isEmpty()) {
return modifiers.get(0).isActive();
} else if (animation != null) return animation.isActive();
IAnimation top = getTopAnimation();
if (top != null) return top.isActive();
return false;
}

@Override
public void get3DTransform(@NotNull PlayerAnimBone bone) {
if (!modifiers.isEmpty()) {
modifiers.getFirst().get3DTransform(bone);
} else if (animation != null) {
animation.get3DTransform(bone);
}
IAnimation top = getTopAnimation();
if (top != null) top.get3DTransform(bone);
}

@Override
public void setupAnim(AnimationData state) {
if (!modifiers.isEmpty()) {
modifiers.get(0).setupAnim(state);
} else if (animation != null) animation.setupAnim(state);
IAnimation top = getTopAnimation();
if (top != null) top.setupAnim(state);
}

@Override
public @NotNull FirstPersonMode getFirstPersonMode() {
if (!modifiers.isEmpty()) {
return modifiers.get(0).getFirstPersonMode();
} else if (animation != null) return animation.getFirstPersonMode();
IAnimation top = getTopAnimation();
if (top != null) return top.getFirstPersonMode();
return IAnimation.super.getFirstPersonMode();
}

@Override
public @NotNull FirstPersonConfiguration getFirstPersonConfiguration() {
if (!modifiers.isEmpty()) {
return modifiers.get(0).getFirstPersonConfiguration();
} else if (animation != null) return animation.getFirstPersonConfiguration();
IAnimation top = getTopAnimation();
if (top != null) return top.getFirstPersonConfiguration();
return IAnimation.super.getFirstPersonConfiguration();
}

Expand All @@ -186,4 +190,10 @@ public String toString() {
", animation=" + animation +
'}';
}

@Override
public void collectModels(Consumer<CustomBone> consumer) {
IAnimation top = getTopAnimation();
if (top != null) top.collectModels(consumer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.zigythebird.playeranimcore.bindings;

public interface PlatformModel {
void invalidate();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this method ever called in the core module? I can't find any instance of it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be called when the animation ends to remove textures from RAM

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.zigythebird.playeranimcore.bones;

import com.zigythebird.playeranimcore.bindings.PlatformModel;
import com.zigythebird.playeranimcore.math.Vec3f;
import org.jetbrains.annotations.Nullable;

public class CustomBone extends PlayerAnimBone {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a big fan of the name, but not sure what to replace it with
Looking at the code all the field and variable names still call instances of this pivot bones
We could still call it PivotBone... IDK
If you remember I am still open to adding a pivot field to the AdvancedPlayerAnimBone, so the bone having pivots could also become a less special attribute of it down the road

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could still call it PivotBone... IDK

No, we can't

If you remember I am still open to adding a pivot field to the AdvancedPlayerAnimBone, so the bone having pivots could also become a less special attribute of it down the road

do it yourself then

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I said I am open to it, not that I want to do it!
Though I might do it... for now that isn't the main topic of discussion

private final Vec3f pivot;

@Nullable
private final PlatformModel model;

public CustomBone(String name, Vec3f pivot, @Nullable PlatformModel model) {
super(name);
this.pivot = pivot;
this.model = model;
}

public Vec3f getPivot() {
return this.pivot;
}

public @Nullable PlatformModel getModel() {
return this.model;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import com.zigythebird.playeranimcore.easing.EasingType;
import com.zigythebird.playeranimcore.enums.Axis;
import com.zigythebird.playeranimcore.enums.TransformType;
import com.zigythebird.playeranimcore.math.MathHelper;
import com.zigythebird.playeranimcore.math.Vec3f;
import org.jetbrains.annotations.ApiStatus;
import org.joml.Vector3f;

Expand Down
Loading