Skip to content

[ENHANCEMENT] WIP: Animation Priority system #5123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions source/funkin/data/animation/AnimationData.hx
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,12 @@ typedef UnnamedAnimationData =
@:default([])
@:optional
var frameIndices:Null<Array<Int>>;

/**
* The priority value for this animation.
* Higher values will be prioritized when playing animations.
*/
@:default(0)
@:optional
var priority:Null<Int>;
}
23 changes: 0 additions & 23 deletions source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,6 @@ class FlxAtlasSprite extends FlxAnimate

var looping:Bool = false;

public var ignoreExclusionPref:Array<String> = [];

/**
* Plays an animation.
* @param id A string ID of the animation to play.
Expand All @@ -127,27 +125,6 @@ class FlxAtlasSprite extends FlxAnimate
*/
public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void
{
// Skip if not allowed to play animations.
if ((!canPlayOtherAnims))
{
if (this.currentAnimation == id && restart) {}
else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0)
{
var detected:Bool = false;
for (entry in ignoreExclusionPref)
{
if (StringTools.startsWith(id, entry))
{
detected = true;
break;
}
}
if (!detected) return;
}
else
return;
}

if (anim == null) return;

if (id == null || id == '') id = this.currentAnimation;
Expand Down
14 changes: 12 additions & 2 deletions source/funkin/play/character/AnimateAtlasCharacter.hx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import funkin.graphics.FunkinSprite;
import flixel.system.FlxAssets.FlxGraphicAsset;
import flixel.util.FlxColor;
import flixel.util.FlxDestroyUtil;
import funkin.data.animation.AnimationData;
import funkin.graphics.adobeanimate.FlxAtlasSprite;
import funkin.modding.events.ScriptEvent;
import funkin.play.character.CharacterData.CharacterRenderType;
Expand Down Expand Up @@ -105,6 +106,15 @@ class AnimateAtlasCharacter extends BaseCharacter
return;
}

var animationPriority = priorityMap.get(correctName);
var currentAnimationPriority = priorityMap.get(getCurrentAnimation());

if (currentAnimationPriority > animationPriority && !isAnimationFinished())
{
trace('Bopper tried to play animation "$name" that has a lower priority than the current animation\'s (${getCurrentAnimation()}) priority! ($currentAnimationPriority)');
return;
}

var animData = getAnimationData(correctName);
currentAnimName = correctName;
var prefix:String = animData.prefix;
Expand Down Expand Up @@ -176,8 +186,6 @@ class AnimateAtlasCharacter extends BaseCharacter

this.mainSprite = sprite;

mainSprite.ignoreExclusionPref = ["sing"];

// This forces the atlas to recalcuate its width and height
this.mainSprite.alpha = 0.0001;
this.mainSprite.draw();
Expand Down Expand Up @@ -217,6 +225,8 @@ class AnimateAtlasCharacter extends BaseCharacter
trace('[ATLASCHAR] - Successfully loaded animation ${anim.name} to ${characterId}');
}

setAnimationPriorities(_data.animations);

trace('[ATLASCHAR] Loaded ${animations.size()} animations for ${characterId}');
}

Expand Down
2 changes: 0 additions & 2 deletions source/funkin/play/character/BaseCharacter.hx
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ class BaseCharacter extends Bopper

this.characterId = id;

ignoreExclusionPref = ["sing"];

_data = CharacterDataParser.fetchCharacterData(this.characterId);
if (_data == null)
{
Expand Down
2 changes: 2 additions & 0 deletions source/funkin/play/character/MultiSparrowCharacter.hx
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class MultiSparrowCharacter extends BaseCharacter
}
}

setAnimationPriorities(_data.animations);

var animNames = this.animation.getNameList();
trace('[MULTISPARROWCHAR] Successfully loaded ${animNames.length} animations for ${characterId}');
}
Expand Down
2 changes: 2 additions & 0 deletions source/funkin/play/character/PackerCharacter.hx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class PackerCharacter extends BaseCharacter
}
}

setAnimationPriorities(_data.animations);

var animNames = this.animation.getNameList();
trace('[PACKERCHAR] Successfully loaded ${animNames.length} animations for ${characterId}');
}
Expand Down
2 changes: 2 additions & 0 deletions source/funkin/play/character/SparrowCharacter.hx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ class SparrowCharacter extends BaseCharacter
}
}

setAnimationPriorities(_data.animations);

var animNames = this.animation.getNameList();
trace('[SPARROWCHAR] Successfully loaded ${animNames.length} animations for ${characterId}');
}
Expand Down
49 changes: 23 additions & 26 deletions source/funkin/play/stage/Bopper.hx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package funkin.play.stage;
import flixel.FlxCamera;
import flixel.math.FlxPoint;
import flixel.util.FlxTimer;
import funkin.data.animation.AnimationData;
import funkin.modding.IScriptedClass.IPlayStateScriptedClass;
import funkin.modding.events.ScriptEvent;

using StringTools;

typedef AnimationFrameCallback = String->Int->Int->Void;
typedef AnimationFinishedCallback = String->Void;

Expand Down Expand Up @@ -55,6 +58,11 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
return isPixel = value;
}

/**
* A map of animation names with their priority values.
*/
public var priorityMap:Map<String, Int> = new Map<String, Int>();

/**
* Whether this bopper should bop every beat. By default it's true, but when used
* for characters/players, it should be false so it doesn't cut off their animations!!!!!
Expand Down Expand Up @@ -253,8 +261,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass

public var canPlayOtherAnims:Bool = true;

public var ignoreExclusionPref:Array<String> = [];

/**
* @param name The name of the animation to play.
* @param restart Whether to restart the animation if it is already playing.
Expand All @@ -263,40 +269,31 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
*/
public function playAnimation(name:String, restart:Bool = false, ignoreOther:Bool = false, reversed:Bool = false):Void
{
if ((!canPlayOtherAnims))
{
var id = name;
if (getCurrentAnimation() == id && restart) {}
else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0)
{
var detected:Bool = false;
for (entry in ignoreExclusionPref)
{
if (StringTools.startsWith(id, entry))
{
detected = true;
break;
}
}
if (!detected) return;
}
else
return;
}

var correctName = correctAnimationName(name);
if (correctName == null) return;

this.animation.play(correctName, restart, reversed, 0);
var animationPriority = priorityMap.get(correctName);
var currentAnimationPriority = priorityMap.get(getCurrentAnimation());

if (ignoreOther)
if (currentAnimationPriority > animationPriority && !isAnimationFinished())
{
canPlayOtherAnims = false;
trace('Bopper tried to play animation "$name" that has a lower priority than the current animation\'s (${getCurrentAnimation()}) priority! ($currentAnimationPriority)');
return;
}

this.animation.play(correctName, restart, reversed, 0);

applyAnimationOffsets(correctName);
}

public function setAnimationPriorities(animations:Array<AnimationData>):Void
{
for (anim in animations)
{
priorityMap.set(anim.name, anim.priority ?? 0);
}
}

var forceAnimationTimer:FlxTimer = new FlxTimer();

/**
Expand Down
12 changes: 3 additions & 9 deletions source/funkin/play/stage/Stage.hx
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
var isSolidColor = dataProp.assetPath.startsWith('#');
var isAnimated = dataProp.animations.length > 0;

var propSprite:StageProp;
if (dataProp.danceEvery != 0)
{
propSprite = new Bopper(dataProp.danceEvery);
}
else
{
propSprite = new StageProp();
}
var propSprite:Bopper = new Bopper(dataProp.danceEvery);

if (isAnimated)
{
Expand All @@ -186,6 +178,8 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
default: // 'sparrow'
propSprite.loadSparrow(dataProp.assetPath);
}

propSprite.setAnimationPriorities(dataProp.animations);
}
else if (isSolidColor)
{
Expand Down