diff --git a/project.hxp b/project.hxp index 82dbfe8..f7838d8 100644 --- a/project.hxp +++ b/project.hxp @@ -185,6 +185,7 @@ class Project extends HXProject addHaxeFlag("--macro include('flixel', true, ['flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*', 'flixel.addons.tile.FlxRayCastTilemap'])"); addHaxeFlag("--macro addMetadata('@:build(funkin.util.macro.ZProperty.buildZProperty())', 'flixel.FlxBasic')"); addHaxeFlag("--macro addMetadata('@:build(funkin.util.macro.ZProperty.buildRearrangeFunction())', 'flixel.group.FlxTypedGroup')"); + addHaxeFlag("--macro addMetadata('@:build(funkin.util.macro.AnimPriority.build())', 'flixel.animation.FlxAnimation')"); addHaxeFlag('--no-output', FUNKIN_DOX_GENERATION.isEnabled(this)); addHaxeFlag('-xml docs/dox/' + Std.string(target).toLowerCase() + '.xml', FUNKIN_DOX_GENERATION.isEnabled(this)); } diff --git a/src/funkin/FunkinSprite.hx b/src/funkin/FunkinSprite.hx index 2f47d9e..b986e5b 100644 --- a/src/funkin/FunkinSprite.hx +++ b/src/funkin/FunkinSprite.hx @@ -107,47 +107,54 @@ class FunkinSprite extends FlxAnimate */ public var currentAnim(default, null):String = ''; - var animationStunned:Bool = false; - /** * Plays an animation. - * @param name The name of the animation to play. + * @param id The id of the animation to play. * @param restart Should the animation restart if it's already playing? - * @param stunAnimations Should the animations be "stunned" until this one is finished? * @param reversed Should the animation be reversed? */ - public function playAnimation(name:String, ?restart:Bool = false, ?stunAnimations:Bool = false, ?reversed:Bool = false):Void + public function playAnimation(id:String, ?restart:Bool = false, ?reversed:Bool = false):Void { - if (animationStunned) + if (animation?.getByName(id)?.priority ?? 0 < animation?.curAnim?.priority ?? 0) + { return; + } - animation.play(name, restart, reversed); - animationStunned = stunAnimations; - currentAnim = name; + animation.play(id, restart, reversed); + currentAnim = id; } /** * Adds an Animation to the sprite. - * @param name The name of the animation to add. - * @param anim The actual animation name. + * @param id The id of the animation to add. + * @param anim The actual animation name to be used. * @param indices The frame indices to use. (Optional) * @param frameRate The Frame Rate of the animation. (Optional) * @param looped Should the animation loop? (Optional) + * @param flipX Should the animation be flipped horizontally? (Optional) + * @param flipY Should the animation be flipped vertically? (Optional) */ - public function addAnimation(name:String, anim:String, ?indices:Array = null, ?frameRate:Float = 24, ?looped:Bool = true):Void + public function addAnimation(id:String, anim:String, ?priority:Int = 0, ?indices:Array = null, ?frameRate:Float = 24, ?looped:Bool = true, + ?flipX:Bool = false, ?flipY:Bool = false):Void { var atlasAnimList:Array = super.getAnimateAnimations(); if (atlasAnimList.contains(anim)) { - super.addAnimateAtlasAnimation(name, anim, indices, frameRate, looped); + super.addAnimateAtlasAnimation(id, anim, priority, indices, frameRate, looped, flipX, flipY); return; } if (indices != null && indices.length > 0) - animation.addByIndices(name, anim + '0', indices, '', frameRate, looped); + { + animation.addByIndices(id, anim + '0', indices, '', frameRate, looped, flipX, flipY); + } else - animation.addByPrefix(name, anim + '0', frameRate, looped); + { + animation.addByPrefix(id, anim + '0', frameRate, looped, flipX, flipY); + } + + animation.getByName(id).priority = priority; } /** @@ -209,16 +216,16 @@ class FunkinSprite extends FlxAnimate /** * Checks if the animation specified exists. - * @param name The animation name to check for. + * @param id The animation id to check for. * @return If the animation exists. */ - public function animationExists(name:String):Bool + public function animationExists(id:String):Bool { var atlasAnimList:Array = super.getAnimateAnimations(); - if (atlasAnimList.contains(name)) + if (atlasAnimList.contains(id)) return true; - return animation?.exists(name) ?? false; + return animation?.exists(id) ?? false; } /** diff --git a/src/funkin/data/object/ObjectData.hx b/src/funkin/data/object/ObjectData.hx index 3c8416d..cc2c02a 100644 --- a/src/funkin/data/object/ObjectData.hx +++ b/src/funkin/data/object/ObjectData.hx @@ -84,10 +84,12 @@ typedef AnimationData = typedef AnimationDataArray = { - var name:String; + var id:String; var prefix:String; + var priority:Int; + @:optional var ?indices:Array; diff --git a/src/funkin/play/hud/HealthIcon.hx b/src/funkin/play/hud/HealthIcon.hx index ad45cc1..3de8df7 100644 --- a/src/funkin/play/hud/HealthIcon.hx +++ b/src/funkin/play/hud/HealthIcon.hx @@ -118,13 +118,15 @@ class HealthIcon extends FunkinSprite for (anim in metadata.animations) { if (metadata.resolution != null) - animation.add(anim.name, anim.indices, anim.framerate, anim.looped, anim.flipX, anim.flipY); + { + animation.add(anim.id, anim?.indices ?? [0], anim?.framerate ?? 24, anim?.looped ?? true, anim?.flipX ?? false, anim?.flipY ?? false); + animation.getByName(anim.id).priority = anim.priority; + } else { if (anim.indices.length != 0) - animation.addByIndices(anim.name, anim.prefix, anim.indices, '', anim.framerate, anim.looped, anim.flipX, anim.flipY); - else - animation.addByPrefix(anim.name, anim.prefix, anim.framerate, anim.looped, anim.flipX, anim.flipY); + addAnimation(anim.id, anim.prefix, anim?.priority ?? 0, anim?.indices ?? [], anim?.framerate ?? 24, anim?.looped ?? true, anim?.flipX ?? false, + anim?.flipY ?? false); } } @@ -151,7 +153,7 @@ class HealthIcon extends FunkinSprite continue; if (curHealth >= check.minimumHealth && curHealth <= check.maximumHealth) - animation.play(check.anim, true); + playAnimation(check.anim, true); } } diff --git a/src/funkin/play/hud/strumline/NoteHoldCover.hx b/src/funkin/play/hud/strumline/NoteHoldCover.hx index 7b354d7..87a89ce 100644 --- a/src/funkin/play/hud/strumline/NoteHoldCover.hx +++ b/src/funkin/play/hud/strumline/NoteHoldCover.hx @@ -52,16 +52,16 @@ class NoteHoldCover extends FunkinSprite // TODO: make this softcoded loadFrames('gameplay/hud/funkin/strumline/sustainCover'); - addAnimation('start', 'sustain cover pre', null, 24, false); - addAnimation('loop', 'sustain cover', null, 24, true); - addAnimation('end', 'sustain cover end', null, 24, false); + addAnimation('start', 'sustain cover pre', 0, null, 24, false); + addAnimation('loop', 'sustain cover', 0, null, 24, true); + addAnimation('end', 'sustain cover end', 0, null, 24, false); onAnimFinished.add(onAnimationFinished); } - override public function playAnimation(name:String, ?restart:Bool = false, ?stunAnimations:Bool = false, ?reversed:Bool = false):Void + override public function playAnimation(name:String, ?restart:Bool = false, ?reversed:Bool = false):Void { - super.playAnimation(name, restart, stunAnimations, reversed); + super.playAnimation(name, restart, reversed); centerOffsets(); switch (name) diff --git a/src/funkin/play/hud/strumline/NoteSplash.hx b/src/funkin/play/hud/strumline/NoteSplash.hx index a52ccbc..56242ac 100644 --- a/src/funkin/play/hud/strumline/NoteSplash.hx +++ b/src/funkin/play/hud/strumline/NoteSplash.hx @@ -29,7 +29,7 @@ class NoteSplash extends FunkinSprite { for (i in 0...2) { - addAnimation('${direction}-$i', 'note impact ${i + 1} ${direction.color}', null, 24, false); + addAnimation('${direction}-$i', 'note impact ${i + 1} ${direction.color}', 0, null, 24, false); } } diff --git a/src/funkin/play/hud/strumline/StrumlineNote.hx b/src/funkin/play/hud/strumline/StrumlineNote.hx index 012914b..c03184e 100644 --- a/src/funkin/play/hud/strumline/StrumlineNote.hx +++ b/src/funkin/play/hud/strumline/StrumlineNote.hx @@ -19,7 +19,7 @@ class StrumlineNote extends FunkinSprite public var forceActive:Bool = false; /** - * Hold cover over this strumline note. + * Hold cover over this strumline note. * This is never used internally, but is used by Strumline to find it. */ // public var holdCover:NoteHoldCover; @@ -34,10 +34,10 @@ class StrumlineNote extends FunkinSprite setGraphicSize(Std.int(width * 0.7)); updateHitbox(); - addAnimation('static', 'arrow ${direction.name}', null, 24, false); - addAnimation('press', '${direction.name} press', null, 24, false); - addAnimation('confirm', '${direction.name} confirm', null, 24, false); - addAnimation('confirm-hold', '${direction.name} confirm hold', null, 24, false); + addAnimation('static', 'arrow ${direction.name}', 0, null, 24, false); + addAnimation('press', '${direction.name} press', 0, null, 24, false); + addAnimation('confirm', '${direction.name} confirm', 0, null, 24, false); + addAnimation('confirm-hold', '${direction.name} confirm hold', 0, null, 24, false); playAnimation('static'); onAnimFinished.add(onAnimationFinished); } @@ -52,10 +52,10 @@ class StrumlineNote extends FunkinSprite } } - override public function playAnimation(name:String, ?restart:Bool = false, ?stunAnimations:Bool = false, ?reversed:Bool = false):Void + override public function playAnimation(id:String, ?restart:Bool = false, ?reversed:Bool = false):Void { - this.active = (forceActive || isAnimationDynamic(name)); - super.playAnimation(name, restart, stunAnimations, reversed); + this.active = (forceActive || isAnimationDynamic(id)); + super.playAnimation(id, restart, reversed); centerOffsets(); centerOrigin(); diff --git a/src/funkin/ui/freeplay/FreeplayCapsule.hx b/src/funkin/ui/freeplay/FreeplayCapsule.hx index d819745..990a111 100644 --- a/src/funkin/ui/freeplay/FreeplayCapsule.hx +++ b/src/funkin/ui/freeplay/FreeplayCapsule.hx @@ -32,8 +32,8 @@ class FreeplayCapsule extends FlxSpriteGroup super(); capsule = new FunkinSprite().loadFrames('ui/freeplay/capsule/default'); - capsule.addAnimation('selected', 'mp3 capsule w backing0', null, 24); - capsule.addAnimation('unselected', 'mp3 capsule w backing NOT SELECTED', null, 24); + capsule.addAnimation('selected', 'mp3 capsule w backing0', 0, null, 24); + capsule.addAnimation('unselected', 'mp3 capsule w backing NOT SELECTED', 0, null, 24); capsule.scale.set(realScaled, realScaled); add(capsule); @@ -73,7 +73,7 @@ class FreeplayCapsule extends FlxSpriteGroup capsuleText.alpha = selected ? 1 : 0.6; capsuleText.textBlur.visible = selected ? true : false; capsule.offset.x = selected ? 0 : -5; - capsule.animation.play(selected ? "selected" : "unselected"); + capsule.playAnimation(selected ? "selected" : "unselected"); if (capsuleText.tooLong) capsuleText.resetText(); diff --git a/src/funkin/ui/freeplay/PixelIcon.hx b/src/funkin/ui/freeplay/PixelIcon.hx index 5fbb3d4..9d58ba7 100644 --- a/src/funkin/ui/freeplay/PixelIcon.hx +++ b/src/funkin/ui/freeplay/PixelIcon.hx @@ -49,13 +49,13 @@ class PixelIcon extends FunkinSprite if (animated) { active = true; - addAnimation('idle', 'idle', null, 10, true); - addAnimation('confirm', 'confirm', null, 10, false); - addAnimation('confirm-hold', 'confirm-hold', null, 10, true); + addAnimation('idle', 'idle', 0, null, 10, true); + addAnimation('confirm', 'confirm', 0, null, 10, false); + addAnimation('confirm-hold', 'confirm-hold', 0, null, 10, true); - onAnimFinished.add((name:String) -> + onAnimFinished.add((id:String) -> { - if (name == 'confirm') + if (id == 'confirm') playAnimation('confirm-hold'); }); diff --git a/src/funkin/ui/freeplay/backingcards/BoyfriendBackingCard.hx b/src/funkin/ui/freeplay/backingcards/BoyfriendBackingCard.hx index 7c00df6..5de2383 100644 --- a/src/funkin/ui/freeplay/backingcards/BoyfriendBackingCard.hx +++ b/src/funkin/ui/freeplay/backingcards/BoyfriendBackingCard.hx @@ -81,7 +81,7 @@ class BoyfriendBackingCard extends BackingCard add(glow); backingTextYeah = new FunkinSprite(640, 370).loadFrames('ui/freeplay/backingCard/backing-text-yeah'); - backingTextYeah.addAnimation("anim", "BF back card confirm raw", 24, false); + backingTextYeah.addAnimation("anim", "BF back card confirm raw", 0, 24, false); add(backingTextYeah); } diff --git a/src/funkin/ui/freeplay/dj/FreeplayDJ.hx b/src/funkin/ui/freeplay/dj/FreeplayDJ.hx index ceebbf8..62bce31 100644 --- a/src/funkin/ui/freeplay/dj/FreeplayDJ.hx +++ b/src/funkin/ui/freeplay/dj/FreeplayDJ.hx @@ -33,9 +33,9 @@ class FreeplayDJ extends FunkinSprite loadFrames('ui/freeplay/freeplay-boyfriend'); applyStageMatrix = true; - addAnimation('idle', 'Idle', 24, false); - addAnimation('confirm', 'Confirm', 24, false); - addAnimation('intro', 'Intro', 24, false); + addAnimation('idle', 'Idle', 0, 24, false); + addAnimation('confirm', 'Confirm', 0, 24, false); + addAnimation('intro', 'Intro', 0, 24, false); } onAnimFinished.add(onFinishAnim); diff --git a/src/funkin/ui/menu/MenuState.hx b/src/funkin/ui/menu/MenuState.hx index c8ca11b..93d4a39 100644 --- a/src/funkin/ui/menu/MenuState.hx +++ b/src/funkin/ui/menu/MenuState.hx @@ -195,8 +195,8 @@ class MenuState extends FunkinState { var itemSpr:FunkinSprite = new FunkinSprite(0, top + (spacing * i)); itemSpr.loadFrames('ui/menu/items/' + item.id); - itemSpr.addAnimation('idle', item.id + ' idle', [], 30, true); - itemSpr.addAnimation('selected', item.id + ' selected', [], 30, true); + itemSpr.addAnimation('idle', item.id + ' idle', 0, [], 30, true); + itemSpr.addAnimation('selected', item.id + ' selected', 0, [], 30, true); itemSpr.playAnimation('idle'); itemSpr.updateHitbox(); itemSpr.screenCenter(X); @@ -259,10 +259,10 @@ class MenuState extends FunkinState if (menuItemGroup.members.indexOf(item) == curSelected) { camFollow.setPosition(FlxG.width / 2, item.getGraphicMidpoint().y); - item.animation.play('selected', true); + item.playAnimation('selected', true); } else - item.animation.play('idle', true); + item.playAnimation('idle', true); item.centerOffsets(); }); diff --git a/src/funkin/ui/story/StoryModeState.hx b/src/funkin/ui/story/StoryModeState.hx index 9e8d224..dbc68af 100644 --- a/src/funkin/ui/story/StoryModeState.hx +++ b/src/funkin/ui/story/StoryModeState.hx @@ -196,7 +196,7 @@ class StoryModeState extends FunkinState for (spr in grp.members) { if (spr.currentAnim != 'confirm') - spr.animation.play(getIdleAnimationForSprite(spr), false); + spr.playAnimation(getIdleAnimationForSprite(spr), false); } } } diff --git a/src/funkin/ui/title/TitleState.hx b/src/funkin/ui/title/TitleState.hx index 2242ac4..6a85570 100644 --- a/src/funkin/ui/title/TitleState.hx +++ b/src/funkin/ui/title/TitleState.hx @@ -158,25 +158,25 @@ class TitleState extends FunkinState { logoBumpin = new FunkinSprite(-150 + 116, -100 + 106); logoBumpin.frames = Paths.content.sparrowAtlas('ui/title/logoBumpin'); - logoBumpin.animation.addByPrefix('bump', 'logo bumpin', 24, false); - logoBumpin.animation.play('bump'); + logoBumpin.addAnimation('bump', 'logo bumpin', 0, 24, false); + logoBumpin.playAnimation('bump'); logoBumpin.updateHitbox(); logoBumpin.visible = false; add(logoBumpin); gfDance = new FunkinSprite(FlxG.width * 0.4, FlxG.height * 0.07); gfDance.loadFrames('ui/title/gfDanceTitle'); - gfDance.addAnimation('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 24, false); - gfDance.addAnimation('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 24, false); + gfDance.addAnimation('danceLeft', 'gfDance', 0, [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 24, false); + gfDance.addAnimation('danceRight', 'gfDance', 0, [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 24, false); gfDance.updateHitbox(); gfDance.visible = false; add(gfDance); enterSpr = new FunkinSprite(0, FlxG.height * 0.8); enterSpr.loadFrames('ui/title/titleEnter'); - enterSpr.animation.addByPrefix('idle', "Press Enter to Begin", 24); - enterSpr.animation.addByPrefix('press', "ENTER PRESSED", 24); - enterSpr.animation.play('idle'); + enterSpr.addAnimation('idle', "Press Enter to Begin", 0, 24); + enterSpr.addAnimation('press', "ENTER PRESSED", 0, 24); + enterSpr.playAnimation('idle'); enterSpr.updateHitbox(); enterSpr.screenCenter(X); enterSpr.visible = false; @@ -406,12 +406,12 @@ class TitleState extends FunkinState if (logoBumpin != null && logoBumpin.animation != null) { - logoBumpin.animation.play('bump', true); + logoBumpin.playAnimation('bump', true); } if (gfDance != null && gfDance.animation != null) { - gfDance.animation.play('${gfHasDancedLeft ? 'danceLeft' : 'danceRight'}', true); + gfDance.playAnimation('${gfHasDancedLeft ? 'danceLeft' : 'danceRight'}', true); } } diff --git a/src/funkin/util/FlxAnimateUtil.hx b/src/funkin/util/FlxAnimateUtil.hx index e57b26c..9bf70c1 100644 --- a/src/funkin/util/FlxAnimateUtil.hx +++ b/src/funkin/util/FlxAnimateUtil.hx @@ -77,7 +77,7 @@ class FlxAnimateUtil * Adds a Texture Atlas Animation to a sprite. * Frame Labels and Symbols are supported. * @param sprite The sprite to apply this animation to. - * @param name What this animation should be called (e.g. `"run"`). + * @param id What this animation should be called (e.g. `"run"`). * @param prefix The name of the Texture Atlas animation internally. * @param indices An array of numbers indicating what frames to play in what order (e.g. `[0, 1, 2]`). * @param frameRate The speed in frames per second that the animation should play at (e.g. `40` fps), leave ``null`` to use the default framerate. @@ -85,8 +85,8 @@ class FlxAnimateUtil * @param flipX Whether the frames should be flipped horizontally. * @param flipY Whether the frames should be flipped vertically. */ - public static function addAnimateAtlasAnimation(sprite:FlxAnimate, name:String, prefix:String, ?indices:Array, ?frameRate:Float, ?looped:Bool = true, - ?flipX:Bool, ?flipY:Bool):Void + public static function addAnimateAtlasAnimation(sprite:FlxAnimate, id:String, prefix:String, ?priority:Int = 0, ?indices:Array, ?frameRate:Float, + ?looped:Bool = true, ?flipX:Bool, ?flipY:Bool):Void { if (sprite.library == null) return; @@ -109,16 +109,19 @@ class FlxAnimateUtil if (foundLabelFrames.length > 0) { if (indices != null) - sprite.anim.addByFrameLabelIndices(name, newPrefix, indices, frameRate, looped, flipX, flipY); + sprite.anim.addByFrameLabelIndices(id, newPrefix, indices, frameRate, looped, flipX, flipY); else - sprite.anim.addByFrameLabel(name, newPrefix, frameRate, looped, flipX, flipY); + sprite.anim.addByFrameLabel(id, newPrefix, frameRate, looped, flipX, flipY); } else { if (indices != null) - sprite.anim.addBySymbolIndices(name, newPrefix, indices, frameRate, looped, flipX, flipY); + sprite.anim.addBySymbolIndices(id, newPrefix, indices, frameRate, looped, flipX, flipY); else - sprite.anim.addBySymbol(name, newPrefix, frameRate, looped, flipX, flipY); + sprite.anim.addBySymbol(id, newPrefix, frameRate, looped, flipX, flipY); } + + // TODO: idk if this works but i guess we'll find out the hard way + sprite.anim.getByName(id).priority = priority; } } diff --git a/src/funkin/util/FunkinSpriteUtil.hx b/src/funkin/util/FunkinSpriteUtil.hx index 7843cbf..5d20930 100644 --- a/src/funkin/util/FunkinSpriteUtil.hx +++ b/src/funkin/util/FunkinSpriteUtil.hx @@ -63,8 +63,8 @@ class FunkinSpriteUtil for (anim in structure) { - // TODO: Work with flipX and flipY. - sprite.addAnimation(anim.name, anim.prefix, anim?.indices ?? [], anim?.framerate ?? 24, anim?.looped ?? false); + sprite.addAnimation(anim.id, anim.prefix, anim?.priority ?? 0, anim?.indices ?? [], anim?.framerate ?? 24, anim?.looped ?? false, anim?.flipX ?? false, + anim?.flipY ?? false); } return sprite; diff --git a/src/funkin/util/macro/AnimPriority.hx b/src/funkin/util/macro/AnimPriority.hx new file mode 100644 index 0000000..c4ccd66 --- /dev/null +++ b/src/funkin/util/macro/AnimPriority.hx @@ -0,0 +1,31 @@ +package funkin.util.macro; + +#if !display +#if macro +import haxe.macro.Context; +import haxe.macro.Expr; + +@:dox(hide) +class AnimPriority +{ + /** + * Builds the field for the `priority` property. + * @return New `priority` field. + */ + public static macro function build():Array + { + var fields:Array = Context.getBuildFields(); + + fields.push({ + name: 'priority', + doc: 'The current priority that this animation has over upcoming animations.', + access: [Access.APublic], + kind: FieldType.FVar(macro :Int, macro $v{0}), + pos: Context.currentPos(), + }); + + return fields; + } +} +#end +#end