/* * Derived from Epic Fight (https://github.com/Epic-Fight/epicfight) * by the Epic Fight Team, licensed under GPLv3. * Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3. */ package com.tiedup.remake.rig.anim; import com.mojang.datafixers.util.Pair; import com.tiedup.remake.rig.anim.property.AnimationProperty.PlaybackSpeedModifier; import com.tiedup.remake.rig.anim.property.AnimationProperty.PlaybackTimeModifier; import com.tiedup.remake.rig.anim.property.AnimationProperty.StaticAnimationProperty; import com.tiedup.remake.rig.anim.types.DynamicAnimation; import com.tiedup.remake.rig.anim.types.StaticAnimation; import com.tiedup.remake.rig.asset.AssetAccessor; import yesman.epicfight.gameasset.Animations; import com.tiedup.remake.rig.TiedUpRigConstants; import com.tiedup.remake.rig.patch.LivingEntityPatch; public class AnimationPlayer { protected float elapsedTime; protected float prevElapsedTime; protected boolean isEnd; protected boolean doNotResetTime; protected boolean reversed; protected AssetAccessor play; public AnimationPlayer() { this.setPlayAnimation(Animations.EMPTY_ANIMATION); } public void tick(LivingEntityPatch entitypatch) { DynamicAnimation currentPlay = this.getAnimation().get(); DynamicAnimation currentPlayStatic = currentPlay.getRealAnimation().get(); this.prevElapsedTime = this.elapsedTime; float playbackSpeed = currentPlay.getPlaySpeed(entitypatch, currentPlay); PlaybackSpeedModifier playSpeedModifier = currentPlayStatic.getProperty(StaticAnimationProperty.PLAY_SPEED_MODIFIER).orElse(null); if (playSpeedModifier != null) { playbackSpeed = playSpeedModifier.modify(currentPlay, entitypatch, playbackSpeed, this.prevElapsedTime, this.elapsedTime); } this.elapsedTime += TiedUpRigConstants.A_TICK * playbackSpeed * (this.isReversed() && currentPlay.canBePlayedReverse() ? -1.0F : 1.0F); PlaybackTimeModifier playTimeModifier = currentPlayStatic.getProperty(StaticAnimationProperty.ELAPSED_TIME_MODIFIER).orElse(null); if (playTimeModifier != null) { Pair time = playTimeModifier.modify(currentPlay, entitypatch, playbackSpeed, this.prevElapsedTime, this.elapsedTime); this.prevElapsedTime = time.getFirst(); this.elapsedTime = time.getSecond(); } if (this.elapsedTime > currentPlay.getTotalTime()) { if (currentPlay.isRepeat()) { this.prevElapsedTime = this.prevElapsedTime - currentPlay.getTotalTime(); this.elapsedTime %= currentPlay.getTotalTime(); } else { this.elapsedTime = currentPlay.getTotalTime(); currentPlay.end(entitypatch, null, true); this.isEnd = true; } } else if (this.elapsedTime < 0) { if (currentPlay.isRepeat()) { this.prevElapsedTime = currentPlay.getTotalTime() - this.elapsedTime; this.elapsedTime = currentPlay.getTotalTime() + this.elapsedTime; } else { this.elapsedTime = 0.0F; currentPlay.end(entitypatch, null, true); this.isEnd = true; } } } public void reset() { this.elapsedTime = 0; this.prevElapsedTime = 0; this.isEnd = false; } public void setPlayAnimation(AssetAccessor animation) { if (this.doNotResetTime) { this.doNotResetTime = false; this.isEnd = false; } else { this.reset(); } this.play = animation; } public Pose getCurrentPose(LivingEntityPatch entitypatch, float partialTicks) { return this.play.get().getPoseByTime(entitypatch, this.prevElapsedTime + (this.elapsedTime - this.prevElapsedTime) * partialTicks, partialTicks); } public float getElapsedTime() { return this.elapsedTime; } public float getPrevElapsedTime() { return this.prevElapsedTime; } public void setElapsedTimeCurrent(float elapsedTime) { this.elapsedTime = elapsedTime; this.isEnd = false; } public void setElapsedTime(float elapsedTime) { this.elapsedTime = elapsedTime; this.prevElapsedTime = elapsedTime; this.isEnd = false; } public void setElapsedTime(float prevElapsedTime, float elapsedTime) { this.elapsedTime = elapsedTime; this.prevElapsedTime = prevElapsedTime; this.isEnd = false; } public void begin(AssetAccessor animation, LivingEntityPatch entitypatch) { animation.get().tick(entitypatch); } public AssetAccessor getAnimation() { return this.play; } public AssetAccessor getRealAnimation() { return this.play.get().getRealAnimation(); } public void markDoNotResetTime() { this.doNotResetTime = true; } public boolean isEnd() { return this.isEnd; } public void terminate(LivingEntityPatch entitypatch) { this.play.get().end(entitypatch, this.play, true); this.isEnd = true; } public boolean isReversed() { return this.reversed; } public void setReversed(boolean reversed) { this.reversed = reversed; } public boolean isEmpty() { return this.play == Animations.EMPTY_ANIMATION; } @Override public String toString() { return this.getAnimation() + " " + this.prevElapsedTime + " " + this.elapsedTime; } }