Skip to content

Commit 932640b

Browse files
committed
animation priority if it was real
1 parent b99089d commit 932640b

File tree

6 files changed

+83
-49
lines changed

6 files changed

+83
-49
lines changed

assets

source/funkin/data/character/CharacterData.hx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,12 @@ class CharacterDataParser
523523
input.startingAnimation = DEFAULT_STARTINGANIM;
524524
}
525525

526+
if (input.animPriorityQueue == null)
527+
{
528+
var canDance:Bool = [for (a in input.animations) a.name].contains("danceLeft");
529+
input.animPriorityQueue = ["sing*", (canDance ? "dance*" : "idle")];
530+
}
531+
526532
if (input.scale == null)
527533
{
528534
input.scale = DEFAULT_SCALE;
@@ -559,7 +565,7 @@ class CharacterDataParser
559565
input.flipX = DEFAULT_FLIPX;
560566
}
561567

562-
if (input.animations.length == 0 && input.startingAnimation != null)
568+
if (input.animations.length == 0 && (input.startingAnimation != null || input.animPriorityQueue != null))
563569
{
564570
return null;
565571
}
@@ -727,6 +733,12 @@ typedef CharacterData =
727733
*/
728734
var startingAnimation:Null<String>;
729735

736+
/**
737+
* If animations are used, place them here to have some sort of priority queue.
738+
* For example a queue ["sing*", "idle"] would have all animations starting with "sing" on a higher priority than idling.
739+
*/
740+
var animPriorityQueue:Null<Array<String>>;
741+
730742
/**
731743
* Whether or not the whole ass sprite is flipped by default.
732744
* Useful for characters that could also be played (Pico)

source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ class FlxAtlasSprite extends FlxAnimate
4141
*/
4242
public var onAnimationLoop:FlxTypedSignal<String->Void> = new FlxTypedSignal();
4343

44+
/**
45+
* The priority queue for the animations.
46+
* The lower the index an animation has, the higher the priority. Animations not in this array have the highest priority.
47+
*/
48+
public var animPriorityQueue:Array<String> = [];
49+
4450
var currentAnimation:String = '';
4551

4652
var canPlayOtherAnims:Bool = true;
@@ -111,8 +117,6 @@ class FlxAtlasSprite extends FlxAnimate
111117

112118
var looping:Bool = false;
113119

114-
public var ignoreExclusionPref:Array<String> = [];
115-
116120
/**
117121
* Plays an animation.
118122
* @param id A string ID of the animation to play.
@@ -125,25 +129,7 @@ class FlxAtlasSprite extends FlxAnimate
125129
public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void
126130
{
127131
// Skip if not allowed to play animations.
128-
if ((!canPlayOtherAnims))
129-
{
130-
if (this.currentAnimation == id && restart) {}
131-
else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0)
132-
{
133-
var detected:Bool = false;
134-
for (entry in ignoreExclusionPref)
135-
{
136-
if (StringTools.startsWith(id, entry))
137-
{
138-
detected = true;
139-
break;
140-
}
141-
}
142-
if (!detected) return;
143-
}
144-
else
145-
return;
146-
}
132+
if (!canPlayOtherAnims && !canPlayAnimation(id)) return;
147133

148134
if (anim == null) return;
149135

@@ -204,6 +190,31 @@ class FlxAtlasSprite extends FlxAnimate
204190
}
205191
}
206192

193+
/**
194+
* Go over the animation priority queue and see if the requested animation can be played.
195+
* @param name The requested animation to play.
196+
*/
197+
function canPlayAnimation(name:String)
198+
{
199+
var requestedPriority:Int = -1;
200+
var currentPriority:Int = -1;
201+
202+
for (i in 0...animPriorityQueue.length)
203+
{
204+
// Format each priority queue member to fit the ereg format.
205+
var queueEntry:String = "^" + animPriorityQueue[i];
206+
var regFormat:String = queueEntry.replace("*", ".+");
207+
208+
if (regFormat.endsWith(".+")) queueEntry = queueEntry.substring(0, queueEntry.length - 1) + "$.+";
209+
210+
if (new EReg(regFormat, "g").match(name) && requestedPriority == -1) requestedPriority = i;
211+
if (new EReg(regFormat, "g").match(getCurrentAnimation()) && currentPriority == -1) currentPriority = i;
212+
}
213+
214+
// An animation can be played if the requestedPriority is smaller or equal to the currentPriority.
215+
return requestedPriority <= currentPriority;
216+
}
217+
207218
override public function update(elapsed:Float):Void
208219
{
209220
super.update(elapsed);

source/funkin/play/character/AnimateAtlasCharacter.hx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ class AnimateAtlasCharacter extends BaseCharacter
176176

177177
this.mainSprite = sprite;
178178

179-
mainSprite.ignoreExclusionPref = ["sing"];
179+
var canDance:Bool = this.hasAnimation("danceLeft");
180+
mainSprite.animPriorityQueue = _data.animPriorityQueue ?? ["sing*", (canDance ? "dance*" : "idle")];
180181

181182
// This forces the atlas to recalcuate its width and height
182183
this.mainSprite.alpha = 0.0001;

source/funkin/play/character/BaseCharacter.hx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,6 @@ class BaseCharacter extends Bopper
160160

161161
this.characterId = id;
162162

163-
ignoreExclusionPref = ["sing"];
164-
165163
_data = CharacterDataParser.fetchCharacterData(this.characterId);
166164
if (_data == null)
167165
{
@@ -179,6 +177,9 @@ class BaseCharacter extends Bopper
179177
this.singTimeSteps = _data.singTime;
180178
this.globalOffsets = _data.offsets;
181179
this.flipX = _data.flipX;
180+
181+
var canDance:Bool = this.hasAnimation("danceLeft");
182+
this.animPriorityQueue = _data.animPriorityQueue ?? ["sing*", (canDance ? "dance*" : "idle")];
182183
}
183184

184185
shouldBop = false;

source/funkin/play/stage/Bopper.hx

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
4343
*/
4444
public var idleSuffix(default, set):String = '';
4545

46+
/**
47+
* The priority queue for the animations.
48+
* The lower the index an animation has, the higher the priority. Animations not in this array have the highest priority.
49+
*/
50+
public var animPriorityQueue:Array<String> = [];
51+
4652
/**
4753
* If this bopper is rendered with pixel art, disable anti-aliasing.
4854
* @default `false`
@@ -118,7 +124,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
118124
*/
119125
function onAnimationFinished(name:String)
120126
{
121-
// TODO: Can we make a system of like, animation priority or something?
122127
if (!canPlayOtherAnims)
123128
{
124129
canPlayOtherAnims = true;
@@ -253,8 +258,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
253258

254259
public var canPlayOtherAnims:Bool = true;
255260

256-
public var ignoreExclusionPref:Array<String> = [];
257-
258261
/**
259262
* @param name The name of the animation to play.
260263
* @param restart Whether to restart the animation if it is already playing.
@@ -263,26 +266,7 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
263266
*/
264267
public function playAnimation(name:String, restart:Bool = false, ignoreOther:Bool = false, reversed:Bool = false):Void
265268
{
266-
if ((!canPlayOtherAnims))
267-
{
268-
var id = name;
269-
if (getCurrentAnimation() == id && restart) {}
270-
else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0)
271-
{
272-
var detected:Bool = false;
273-
for (entry in ignoreExclusionPref)
274-
{
275-
if (StringTools.startsWith(id, entry))
276-
{
277-
detected = true;
278-
break;
279-
}
280-
}
281-
if (!detected) return;
282-
}
283-
else
284-
return;
285-
}
269+
if (!canPlayOtherAnims && !canPlayAnimation(name)) return;
286270

287271
var correctName = correctAnimationName(name);
288272
if (correctName == null) return;
@@ -297,6 +281,31 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
297281
applyAnimationOffsets(correctName);
298282
}
299283

284+
/**
285+
* Go over the animation priority queue and see if the requested animation can be played.
286+
* @param name The requested animation to play.
287+
*/
288+
function canPlayAnimation(name:String)
289+
{
290+
var requestedPriority:Int = -1;
291+
var currentPriority:Int = -1;
292+
293+
for (i in 0...animPriorityQueue.length)
294+
{
295+
// Format each priority queue member to fit the ereg format.
296+
var queueEntry:String = "^" + animPriorityQueue[i];
297+
var regFormat:String = queueEntry.replace("*", ".+");
298+
299+
if (regFormat.endsWith(".+")) queueEntry = queueEntry.substring(0, queueEntry.length - 1) + "$.+";
300+
301+
if (new EReg(regFormat, "g").match(name) && requestedPriority == -1) requestedPriority = i;
302+
if (new EReg(regFormat, "g").match(getCurrentAnimation()) && currentPriority == -1) currentPriority = i;
303+
}
304+
305+
// An animation can be played if the requestedPriority is smaller or equal to the currentPriority.
306+
return requestedPriority <= currentPriority;
307+
}
308+
300309
var forceAnimationTimer:FlxTimer = new FlxTimer();
301310

302311
/**

0 commit comments

Comments
 (0)