Skip to content

Commit

Permalink
More Anim Notify Progress
Browse files Browse the repository at this point in the history
- Deprecated old state machine animation sequence stuff
- Added "AnimNotifies" class
  • Loading branch information
Trainguy9512 committed Feb 5, 2025
1 parent 9359587 commit 375429c
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,6 @@ public AnimationBlendSpacePlayer build() {
}
}

public AnimationBlendSpacePlayer addEntry(float position, ResourceLocation resourceLocation, float playRate){
blendSpaceEntryTreeMap.put(position, new BlendSpaceEntry(resourceLocation, playRate));
return this;
}

public AnimationBlendSpacePlayer setPlayRateMultipler(float newPlayRate){
this.playRateMultiplier = newPlayRate;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class AnimationMontage {
private float playRate = 1;
private float blendInDuration = 1;
private float blendOutDuration = 1;
private Easing blendInEasing = Easing.Linear.of();
private Easing blendOutEasing = Easing.Linear.of();
private Easing blendInEasing = Easing.LINEAR;
private Easing blendOutEasing = Easing.LINEAR;

public float timeElapsed = 0;
private boolean active = true;
Expand All @@ -32,10 +32,10 @@ public static AnimationMontage of(ResourceLocation resourceLocation){
}

public void tick(){
// Tick time forwards using the playrare
// Tick time forwards using the play rate
this.timeElapsed += this.playRate;

// Only make the active state changable when its active. Once it becomes deactive, it will be destroyed upon blendWeight == 0
// Only make the active state changeable when its active. Once it becomes deactive, it will be destroyed upon blendWeight == 0
if(isActive()){
setActive(this.timeElapsed < this.length);
}
Expand All @@ -45,7 +45,7 @@ public void tick(){
}

public <L extends Enum<L>> AnimationPose<L> getAnimationPose(JointSkeleton<L> jointSkeleton){
return AnimationPose.fromAnimationSequence(jointSkeleton, this.resourceLocation, (this.timeElapsed + this.startOffset) / AnimationSequenceData.INSTANCE.get(resourceLocation).getFrameLength());
return AnimationPose.fromAnimationSequence(jointSkeleton, this.resourceLocation, (this.timeElapsed + this.startOffset) / AnimationSequenceData.INSTANCE.get(resourceLocation).frameLength());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.trainguy9512.animationoverhaul.animation.pose.sample;

import com.trainguy9512.animationoverhaul.animation.data.AnimationDriverContainer;
import com.trainguy9512.animationoverhaul.animation.data.PoseSamplerStateContainer;
import com.trainguy9512.animationoverhaul.animation.pose.AnimationPose;
import com.trainguy9512.animationoverhaul.animation.pose.JointSkeleton;
import net.minecraft.util.Mth;
import java.util.ArrayList;

public class AnimationMontageTrack extends PoseSampler {
public class AnimationMontageTrack extends PoseSampler implements SampleableFromInput {

private final ArrayList<AnimationMontage> activeMontages = new ArrayList<AnimationMontage>();

Expand All @@ -31,9 +33,9 @@ public AnimationMontageTrack build() {
}

@Override
public void tick(){
public void tick(AnimationDriverContainer animationDriverContainer, PoseSamplerStateContainer poseSamplerStateContainer){
// Only run if there's actually montages currently loaded
if(this.isActive()){
if(this.hasActiveMontages()){
ArrayList<AnimationMontage> montagesToRemove = new ArrayList<>();
for(AnimationMontage animationMontage : activeMontages){
animationMontage.tick();
Expand All @@ -50,20 +52,12 @@ public void tick(){
}

@Override
public <L extends Enum<L>> AnimationPose<L> sampleFromInputPose(AnimationPose<L> inputPose, JointSkeleton<L> jointSkeleton) {
return getBlendedPose(inputPose, jointSkeleton);
}

public boolean isActive(){
return !this.activeMontages.isEmpty();
}

private <L extends Enum<L>> AnimationPose<L> getBlendedPose(AnimationPose<L> inputPose, JointSkeleton<L> jointSkeleton){
public AnimationPose sample(AnimationDriverContainer animationDriverContainer, PoseSamplerStateContainer poseSamplerStateContainer, JointSkeleton jointSkeleton, AnimationPose inputPose) {
// Initialize the animation pose
AnimationPose<L> animationPose = AnimationPose.of(jointSkeleton);
AnimationPose animationPose = AnimationPose.of(jointSkeleton);

// Only do this stuff if there's any loaded animation montages
if(this.isActive()){
if(this.hasActiveMontages()){
// Iterate over each montage and get the blended animation between top and bottom layers
for(int i = 0; i < this.activeMontages.size(); i++){
AnimationMontage animationMontage = this.activeMontages.get(i);
Expand All @@ -86,6 +80,10 @@ private <L extends Enum<L>> AnimationPose<L> getBlendedPose(AnimationPose<L> inp
return animationPose;
}

public boolean hasActiveMontages(){
return !this.activeMontages.isEmpty();
}

/**
* Plays the given montage. Should be accessed within the tick phase for intended functionality
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static Builder<?> of(ResourceLocation resourceLocation){

@Override
public AnimationPose sample(AnimationDriverContainer animationDriverContainer, PoseSamplerStateContainer poseSamplerStateContainer, JointSkeleton jointSkeleton) {
return AnimationPose.fromAnimationSequence(jointSkeleton, this.resourceLocation, this.getTimeFromTicks());
return AnimationPose.fromAnimationSequence(jointSkeleton, this.resourceLocation, this.processTime(this.getTimeElapsed()));
}


Expand Down Expand Up @@ -97,10 +97,10 @@ public void tick(AnimationDriverContainer animationDriverContainer, PoseSamplerS
super.tick(animationDriverContainer, poseSamplerStateContainer);
}

private float getTimeFromTicks(){
private float processTime(float inputTime){
return this.looping ?
(((this.getTimeElapsed()) % (this.endTime - this.startTime)) + this.startTime) / this.frameLength :
Mth.clamp(this.getTimeElapsed(), 0, this.endTime) / this.frameLength;
(((inputTime) % (this.endTime - this.startTime)) + this.startTime) / this.frameLength :
Mth.clamp(inputTime, 0, this.endTime) / this.frameLength;
}

public float getTimeElapsedLooped(){
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
package com.trainguy9512.animationoverhaul.animation.pose.sample;

import com.google.common.collect.Maps;
import com.trainguy9512.animationoverhaul.animation.data.AnimationDriverContainer;
import com.trainguy9512.animationoverhaul.animation.data.PoseSamplerKey;
import com.trainguy9512.animationoverhaul.animation.data.PoseSamplerStateContainer;
import com.trainguy9512.animationoverhaul.animation.pose.sample.notify.AnimNotify;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class TimeBasedPoseSampler extends PoseSampler {

protected float timeElapsed;
private float playRate;
private boolean playing;
private final HashMap<PoseSamplerKey<? extends AnimationStateMachine<?>>, List<Enum<?>>> playFromStartOnActiveStates;
private final HashMap<PoseSamplerKey<? extends AnimationStateMachine<?>>, List<Enum<?>>> progressTimeOnActiveStates;
private boolean resetting;

protected TimeBasedPoseSampler(Builder<?> builder) {
super(builder);
this.timeElapsed = 0;
this.playRate = builder.playRate;
this.playing = builder.isPlaying;
this.playFromStartOnActiveStates = builder.playFromStartOnActiveStates;
this.progressTimeOnActiveStates = builder.progressTimeOnActiveStates;
this.playing = builder.playing;
this.resetting = false;
}

public static Builder<?> of(){
Expand All @@ -34,14 +30,10 @@ public static Builder<?> of(){
public static class Builder<B extends Builder<B>> extends PoseSampler.Builder<B> {

private float playRate = 1;
private boolean isPlaying = true;
private final HashMap<PoseSamplerKey<? extends AnimationStateMachine<?>>, List<Enum<?>>> playFromStartOnActiveStates;
private final HashMap<PoseSamplerKey<? extends AnimationStateMachine<?>>, List<Enum<?>>> progressTimeOnActiveStates;
private boolean playing = true;

protected Builder() {
super();
this.playFromStartOnActiveStates = Maps.newHashMap();
this.progressTimeOnActiveStates = Maps.newHashMap();
}

@SuppressWarnings("unchecked")
Expand All @@ -51,26 +43,8 @@ public B setPlayRate(float playRate){
}

@SuppressWarnings("unchecked")
public B setIsPlaying(boolean isPlaying){
this.isPlaying = isPlaying;
return (B) this;
}

@SuppressWarnings("unchecked")
public <S extends Enum<S>> B addPlayFromStartOnActiveStates(PoseSamplerKey<AnimationStateMachine<S>> animationStateMachineKey, Enum<S>... states){
this.playFromStartOnActiveStates.putIfAbsent(animationStateMachineKey, new ArrayList<>());
for(Enum<S> state : states){
this.playFromStartOnActiveStates.get(animationStateMachineKey).add(state);
}
return (B) this;
}

@SuppressWarnings("unchecked")
public <S extends Enum<S>> B addProgressTimeOnActiveStates(PoseSamplerKey<AnimationStateMachine<S>> animationStateMachineKey, Enum<S>... states){
this.progressTimeOnActiveStates.putIfAbsent( animationStateMachineKey, new ArrayList<>());
for(Enum<S> state : states){
this.progressTimeOnActiveStates.get(animationStateMachineKey).add(state);
}
public B setPlaying(boolean playing){
this.playing = playing;
return (B) this;
}

Expand All @@ -92,62 +66,29 @@ public void setTimeElapsed(float timeElapsed){
this.timeElapsed = timeElapsed;
}

public void resetTime(){
this.setTimeElapsed(0);
}

public boolean getIsPlaying(){
return this.playing;
}

public float getTimeElapsed(){
return this.timeElapsed;
}

public void resetTime(){
this.setTimeElapsed(0);
this.resetting = true;
}

/**
* Iterates over all state machines/state enums listed for playing from start on state active, and if the state is currently not active then it repeatedly resets until the state is active.
*/
public void playFromStartOnStateActive(PoseSamplerStateContainer poseSamplerStateContainer){
if(!this.playFromStartOnActiveStates.isEmpty()) {
for (PoseSamplerKey<? extends AnimationStateMachine<?>> animationStateMachineKey : this.playFromStartOnActiveStates.keySet()) {
AnimationStateMachine<?> animationStateMachine = poseSamplerStateContainer.getPoseSampler(animationStateMachineKey);

for (Enum<?> stateEnum : this.playFromStartOnActiveStates.get(animationStateMachineKey)) {
if (animationStateMachine.getActiveStates().contains(stateEnum)) {
return;
}
}
}
this.resetTime();
}
public void setPlaying(boolean playing){
this.playing = playing;
}

/**
* Iterates over all state machine/state enums listed for progressing time on state active, and if any of the states are active then time is progressed.
*/
public void progressTimeIfStateActive(PoseSamplerStateContainer poseSamplerStateContainer){
if(!this.progressTimeOnActiveStates.isEmpty()){
for(PoseSamplerKey<? extends AnimationStateMachine<?>> animationStateMachineKey : this.progressTimeOnActiveStates.keySet()){
AnimationStateMachine<?> animationStateMachine = poseSamplerStateContainer.getPoseSampler(animationStateMachineKey);

for(Enum<?> stateEnum : this.progressTimeOnActiveStates.get(animationStateMachineKey)){
if(animationStateMachine.getActiveStates().contains(stateEnum)){
this.playing = true;
return;
}
}
}
this.playing = false;
}
public boolean getPlaying(){
return this.playing;
}


@Override
public void tick(AnimationDriverContainer animationDriverContainer, PoseSamplerStateContainer poseSamplerStateContainer){
progressTimeIfStateActive(poseSamplerStateContainer);
if(this.getIsPlaying()){
if(this.getPlaying() && !this.resetting){
this.timeElapsed += this.playRate;
}
playFromStartOnStateActive(poseSamplerStateContainer);
this.resetting = false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.trainguy9512.animationoverhaul.animation.pose.sample.notify;

import com.trainguy9512.animationoverhaul.animation.data.PoseSamplerKey;
import com.trainguy9512.animationoverhaul.animation.pose.sample.TimeBasedPoseSampler;

/**
* Class with preset anim notify functions
*/
public class AnimNotifies {

/**
* Provides an anim notify that resets the time on the time-based pose sampler associated with the provided key.
* @param poseSamplerKey Time-based pose sampler key to reset the time on.
*/
public static AnimNotify resetTimeAnimNotify(PoseSamplerKey<TimeBasedPoseSampler> poseSamplerKey){
return (animationDriverContainer, poseSamplerStateContainer) -> poseSamplerStateContainer.getPoseSampler(poseSamplerKey).resetTime();
}
}

0 comments on commit 375429c

Please sign in to comment.