From e3b37a95775b4e59498550e82dba538ad46e75d2 Mon Sep 17 00:00:00 2001 From: GeckoThePecko Date: Tue, 14 Nov 2023 15:42:29 -0500 Subject: [PATCH] fix(animation-transitions): missing transition interpolation for edge case where there are no keyframes in a destination animation --- gradle.properties | 2 +- .../geckolib3/core/builder/Animation.java | 3 +- .../core/controller/AnimationController.java | 86 +++++++++++-------- 3 files changed, 54 insertions(+), 37 deletions(-) diff --git a/gradle.properties b/gradle.properties index 552c761..7063c2e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ #Publishing -version=1.0.5 +version=1.0.6 group=software.bernie.geckolib3 archivesBaseName=core \ No newline at end of file diff --git a/src/main/java/software/bernie/geckolib3/core/builder/Animation.java b/src/main/java/software/bernie/geckolib3/core/builder/Animation.java index 8b06abe..a1faabb 100644 --- a/src/main/java/software/bernie/geckolib3/core/builder/Animation.java +++ b/src/main/java/software/bernie/geckolib3/core/builder/Animation.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * A specific animation instance @@ -20,7 +21,7 @@ public class Animation public String animationName; public Double animationLength; public boolean loop = true; - public List boneAnimations; + public Map boneAnimations; public List> soundKeyFrames = new ArrayList<>(); public List particleKeyFrames = new ArrayList<>(); public List> customInstructionKeyframes = new ArrayList<>(); diff --git a/src/main/java/software/bernie/geckolib3/core/controller/AnimationController.java b/src/main/java/software/bernie/geckolib3/core/controller/AnimationController.java index 8532b91..9e7259b 100644 --- a/src/main/java/software/bernie/geckolib3/core/controller/AnimationController.java +++ b/src/main/java/software/bernie/geckolib3/core/controller/AnimationController.java @@ -418,33 +418,27 @@ public void process(double tick, AnimationEvent event, List modelRende } if (currentAnimation != null) { setAnimTime(context, 0); - for (BoneAnimation boneAnimation : currentAnimation.boneAnimations) { - BoneAnimationQueue boneAnimationQueue = boneAnimationQueues.get(boneAnimation.boneName); - BoneSnapshot boneSnapshot = this.boneSnapshots.get(boneAnimation.boneName); - Optional first = modelRendererList.stream() - .filter(x -> x.getName().equals(boneAnimation.boneName)).findFirst(); - if (!first.isPresent()) { - if (crashWhenCantFindBone) { - throw new RuntimeException("Could not find bone: " + boneAnimation.boneName); - } else { - continue; - } + for (IBone bone : modelRendererList) { + BoneAnimationQueue boneAnimationQueue = boneAnimationQueues.get(bone.getName()); + BoneSnapshot boneSnapshot = this.boneSnapshots.get(bone.getName()); + + if(boneSnapshot == null) { + continue; } - BoneSnapshot initialSnapshot = first.get().getInitialSnapshot(); - assert boneSnapshot != null : "Bone snapshot was null"; - VectorKeyFrameList> rotationKeyFrames = boneAnimation.rotationKeyFrames; - VectorKeyFrameList> positionKeyFrames = boneAnimation.positionKeyFrames; - VectorKeyFrameList> scaleKeyFrames = boneAnimation.scaleKeyFrames; + BoneSnapshot initialSnapshot = bone.getInitialSnapshot(); + + //can be null + BoneAnimation boneAnimation = currentAnimation.boneAnimations.get(bone.getName()); // Adding the initial positions of the upcoming animation, so the model // transitions to the initial state of the new animation - if (!rotationKeyFrames.xKeyFrames.isEmpty()) { - AnimationPoint xPoint = getTransitionPointAtTick(context, rotationKeyFrames.xKeyFrames, tick, true, Axis.X, + if (boneAnimation != null && !boneAnimation.rotationKeyFrames.xKeyFrames.isEmpty()) { + AnimationPoint xPoint = getTransitionPointAtTick(context, boneAnimation.rotationKeyFrames.xKeyFrames, tick, true, Axis.X, evaluator); - AnimationPoint yPoint = getTransitionPointAtTick(context, rotationKeyFrames.yKeyFrames, tick, true, Axis.Y, + AnimationPoint yPoint = getTransitionPointAtTick(context, boneAnimation.rotationKeyFrames.yKeyFrames, tick, true, Axis.Y, evaluator); - AnimationPoint zPoint = getTransitionPointAtTick(context, rotationKeyFrames.zKeyFrames, tick, true, Axis.Z, + AnimationPoint zPoint = getTransitionPointAtTick(context, boneAnimation.rotationKeyFrames.zKeyFrames, tick, true, Axis.Z, evaluator); boneAnimationQueue.rotationXQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, boneSnapshot.rotationValueX - initialSnapshot.rotationValueX, @@ -456,13 +450,24 @@ public void process(double tick, AnimationEvent event, List modelRende boneSnapshot.rotationValueZ - initialSnapshot.rotationValueZ, zPoint.animationStartValue)); } + else { + boneAnimationQueue.rotationXQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.rotationValueX - initialSnapshot.rotationValueX, + initialSnapshot.rotationValueX)); + boneAnimationQueue.rotationYQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.rotationValueY - initialSnapshot.rotationValueY, + initialSnapshot.rotationValueY)); + boneAnimationQueue.rotationZQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.rotationValueZ - initialSnapshot.rotationValueZ, + initialSnapshot.rotationValueZ)); + } - if (!positionKeyFrames.xKeyFrames.isEmpty()) { - AnimationPoint xPoint = getTransitionPointAtTick(context, positionKeyFrames.xKeyFrames, tick, false, Axis.X, + if (boneAnimation != null && !boneAnimation.positionKeyFrames.xKeyFrames.isEmpty()) { + AnimationPoint xPoint = getTransitionPointAtTick(context, boneAnimation.positionKeyFrames.xKeyFrames, tick, false, Axis.X, evaluator); - AnimationPoint yPoint = getTransitionPointAtTick(context, positionKeyFrames.yKeyFrames, tick, false, Axis.Y, + AnimationPoint yPoint = getTransitionPointAtTick(context, boneAnimation.positionKeyFrames.yKeyFrames, tick, false, Axis.Y, evaluator); - AnimationPoint zPoint = getTransitionPointAtTick(context, positionKeyFrames.zKeyFrames, tick, false, Axis.Z, + AnimationPoint zPoint = getTransitionPointAtTick(context, boneAnimation.positionKeyFrames.zKeyFrames, tick, false, Axis.Z, evaluator); boneAnimationQueue.positionXQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, boneSnapshot.positionOffsetX, xPoint.animationStartValue)); @@ -471,13 +476,21 @@ public void process(double tick, AnimationEvent event, List modelRende boneAnimationQueue.positionZQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, boneSnapshot.positionOffsetZ, zPoint.animationStartValue)); } + else { + boneAnimationQueue.positionXQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.positionOffsetX, initialSnapshot.positionOffsetX)); + boneAnimationQueue.positionYQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.positionOffsetY, initialSnapshot.positionOffsetY)); + boneAnimationQueue.positionZQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.positionOffsetZ, initialSnapshot.positionOffsetZ)); + } - if (!scaleKeyFrames.xKeyFrames.isEmpty()) { - AnimationPoint xPoint = getTransitionPointAtTick(context, scaleKeyFrames.xKeyFrames, tick, false, Axis.X, + if (boneAnimation != null && !boneAnimation.scaleKeyFrames.xKeyFrames.isEmpty()) { + AnimationPoint xPoint = getTransitionPointAtTick(context, boneAnimation.scaleKeyFrames.xKeyFrames, tick, false, Axis.X, evaluator); - AnimationPoint yPoint = getTransitionPointAtTick(context, scaleKeyFrames.yKeyFrames, tick, false, Axis.Y, + AnimationPoint yPoint = getTransitionPointAtTick(context, boneAnimation.scaleKeyFrames.yKeyFrames, tick, false, Axis.Y, evaluator); - AnimationPoint zPoint = getTransitionPointAtTick(context, scaleKeyFrames.zKeyFrames, tick, false, Axis.Z, + AnimationPoint zPoint = getTransitionPointAtTick(context, boneAnimation.scaleKeyFrames.zKeyFrames, tick, false, Axis.Z, evaluator); boneAnimationQueue.scaleXQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, boneSnapshot.scaleValueX, xPoint.animationStartValue)); @@ -486,6 +499,14 @@ public void process(double tick, AnimationEvent event, List modelRende boneAnimationQueue.scaleZQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, boneSnapshot.scaleValueZ, zPoint.animationStartValue)); } + else { + boneAnimationQueue.scaleXQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.scaleValueX, initialSnapshot.scaleValueX)); + boneAnimationQueue.scaleYQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.scaleValueY, initialSnapshot.scaleValueY)); + boneAnimationQueue.scaleZQueue.add(new AnimationPoint(null, tick, transitionLengthTicks, + boneSnapshot.scaleValueZ, initialSnapshot.scaleValueZ)); + } } } } else if (getAnimationState() == AnimationState.Running) { @@ -522,11 +543,7 @@ protected PlayState testAnimationPredicate(AnimationEvent event) { private void saveSnapshotsForAnimation(Animation animation, HashMap> boneSnapshotCollection) { for (Pair snapshot : boneSnapshotCollection.values()) { - if (animation != null && animation.boneAnimations != null) { - if (animation.boneAnimations.stream().anyMatch(x -> x.boneName.equals(snapshot.getLeft().getName()))) { - this.boneSnapshots.put(snapshot.getLeft().getName(), new BoneSnapshot(snapshot.getRight())); - } - } + this.boneSnapshots.put(snapshot.getLeft().getName(), new BoneSnapshot(snapshot.getRight())); } } @@ -562,8 +579,7 @@ private void processCurrentAnimation(double tick, double actualTick, Evaluator e // Loop through every boneanimation in the current animation and process the // values - List boneAnimations = currentAnimation.boneAnimations; - for (BoneAnimation boneAnimation : boneAnimations) { + for (BoneAnimation boneAnimation : currentAnimation.boneAnimations.values()) { BoneAnimationQueue boneAnimationQueue = boneAnimationQueues.get(boneAnimation.boneName); if (boneAnimationQueue == null) { if (crashWhenCantFindBone) {