Skip to content

Commit

Permalink
fix(animation-transitions): missing transition interpolation for edge…
Browse files Browse the repository at this point in the history
… case where there are no keyframes in a destination animation
  • Loading branch information
bernie-g committed Nov 14, 2023
1 parent 9a40f94 commit e3b37a9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 37 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Publishing
version=1.0.5
version=1.0.6
group=software.bernie.geckolib3
archivesBaseName=core
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* A specific animation instance
Expand All @@ -20,7 +21,7 @@ public class Animation
public String animationName;
public Double animationLength;
public boolean loop = true;
public List<BoneAnimation> boneAnimations;
public Map<String, BoneAnimation> boneAnimations;
public List<EventKeyFrame<String>> soundKeyFrames = new ArrayList<>();
public List<ParticleEventKeyFrame> particleKeyFrames = new ArrayList<>();
public List<EventKeyFrame<String>> customInstructionKeyframes = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,33 +418,27 @@ public void process(double tick, AnimationEvent<T> event, List<IBone> 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<IBone> 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<KeyFrame<Evaluatable>> rotationKeyFrames = boneAnimation.rotationKeyFrames;
VectorKeyFrameList<KeyFrame<Evaluatable>> positionKeyFrames = boneAnimation.positionKeyFrames;
VectorKeyFrameList<KeyFrame<Evaluatable>> 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,
Expand All @@ -456,13 +450,24 @@ public void process(double tick, AnimationEvent<T> event, List<IBone> 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));
Expand All @@ -471,13 +476,21 @@ public void process(double tick, AnimationEvent<T> event, List<IBone> 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));
Expand All @@ -486,6 +499,14 @@ public void process(double tick, AnimationEvent<T> event, List<IBone> 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) {
Expand Down Expand Up @@ -522,11 +543,7 @@ protected PlayState testAnimationPredicate(AnimationEvent<T> event) {
private void saveSnapshotsForAnimation(Animation animation,
HashMap<String, Pair<IBone, BoneSnapshot>> boneSnapshotCollection) {
for (Pair<IBone, BoneSnapshot> 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()));
}
}

Expand Down Expand Up @@ -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<BoneAnimation> boneAnimations = currentAnimation.boneAnimations;
for (BoneAnimation boneAnimation : boneAnimations) {
for (BoneAnimation boneAnimation : currentAnimation.boneAnimations.values()) {
BoneAnimationQueue boneAnimationQueue = boneAnimationQueues.get(boneAnimation.boneName);
if (boneAnimationQueue == null) {
if (crashWhenCantFindBone) {
Expand Down

0 comments on commit e3b37a9

Please sign in to comment.