Invalid Animation support!!! :D

This commit is contained in:
lunarcleint
2025-02-24 14:17:12 -07:00
parent 5ed03ce0fa
commit a65c21edb7
7 changed files with 146 additions and 43 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

@@ -1,5 +1,7 @@
package funkin.editors.character; package funkin.editors.character;
import flixel.text.FlxText.FlxTextFormat;
import flixel.text.FlxText.FlxTextFormatMarkerPair;
import flxanimate.animate.FlxAnim.FlxSymbolAnimation; import flxanimate.animate.FlxAnim.FlxSymbolAnimation;
import flxanimate.animate.FlxSymbol; import flxanimate.animate.FlxSymbol;
import flxanimate.animate.FlxElement; import flxanimate.animate.FlxElement;
@@ -17,6 +19,7 @@ using StringTools;
class CharacterAnimButton extends UIButton { class CharacterAnimButton extends UIButton {
public var anim:String = null; public var anim:String = null;
public var valid:Bool = true;
public var data:AnimData = null; public var data:AnimData = null;
public var parent:CharacterAnimsWindow; public var parent:CharacterAnimsWindow;
@@ -38,7 +41,7 @@ class CharacterAnimButton extends UIButton {
public var ghostButton:UIButton; public var ghostButton:UIButton;
public var ghostIcon:FlxSprite; public var ghostIcon:FlxSprite;
public var playIcon:FlxSprite; public var animIcon:FlxSprite;
public var labels:Map<UISprite, UIText> = []; public var labels:Map<UISprite, UIText> = [];
@@ -125,10 +128,14 @@ class CharacterAnimButton extends UIButton {
foldableButtons.push(indicesTextBox); foldableButtons.push(indicesTextBox);
addLabelOn(indicesTextBox, "Indices (frames)", 12); addLabelOn(indicesTextBox, "Indices (frames)", 12);
playIcon = new FlxSprite(x-(10+16), y+8).loadGraphic(Paths.image("editors/character/play")); animIcon = new FlxSprite(x-(10+16), y+8).loadGraphic(Paths.image("editors/character/anim-icons"), true, 16, 12);
// playIcon.color = 0xFFD60E0E; animIcon.animation.add("play", [0]);
playIcon.antialiasing = false; animIcon.animation.add("error", [1]);
members.push(playIcon); // animIcon.color = 0xFFD60E0E;
animIcon.animation.play("play");
animIcon.antialiasing = false;
animIcon.updateHitbox();
members.push(animIcon);
deleteButton = new UIButton(0, 0, null, () -> {parent.deleteAnimation(this);}, 28*2,24); deleteButton = new UIButton(0, 0, null, () -> {parent.deleteAnimation(this);}, 28*2,24);
deleteButton.frames = Paths.getFrames("editors/ui/grayscale-button"); deleteButton.frames = Paths.getFrames("editors/ui/grayscale-button");
@@ -164,10 +171,12 @@ class CharacterAnimButton extends UIButton {
ghostIcon.antialiasing = false; ghostIcon.antialiasing = false;
ghostIcon.updateHitbox(); ghostIcon.updateHitbox();
members.push(ghostIcon); members.push(ghostIcon);
checkValid();
} }
public inline function updateButtonsPos() { public inline function updateButtonsPos() {
playIcon.follow(this, 22, (52/2) - (playIcon.height/2)); animIcon.follow(this, 22, (52/2) - (animIcon.height/2) + (animIcon.animation.name == "error" ? 2 : 0));
field.follow(this, 22+16+10, (52/2) - (field.height/2) + 1); field.follow(this, 22+16+10, (52/2) - (field.height/2) + 1);
deleteButton.follow(this, 380, 14); deleteButton.follow(this, 380, 14);
@@ -216,12 +225,12 @@ class CharacterAnimButton extends UIButton {
} }
if (parent.character.animateAtlas != null) { if (parent.character.animateAtlas != null) {
var animSymbol:FlxSymbolAnimation = parent.character.animateAtlas.anim.animsMap[anim]; var animSymbol:FlxSymbolAnimation = __getAnimationSymbol();
parent.character.animateAtlas.anim.animsMap.remove(anim); parent.character.animateAtlas.anim.animsMap.remove(anim);
parent.character.animateAtlas.anim.animsMap.set(newName, animSymbol); parent.character.animateAtlas.anim.animsMap.set(newName, animSymbol);
} else { } else {
var flxAnimation:FlxAnimation = parent.character.animation._animations[anim]; var flxAnimation:FlxAnimation = __getFlxAnimation();
flxAnimation.name = newName; flxAnimation.name = newName;
parent.character.animation._animations.remove(anim); parent.character.animation._animations.remove(anim);
@@ -243,7 +252,7 @@ class CharacterAnimButton extends UIButton {
parent.displayAnimsFramesList.set(newName, displayFrame); parent.displayAnimsFramesList.set(newName, displayFrame);
this.anim = newName; this.anim = newName;
field.text = '${animData.name} (${animData.x}, ${animData.y})'; updateText();
} }
public function changeAnim(newAnim:String) @:privateAccess { public function changeAnim(newAnim:String) @:privateAccess {
@@ -251,15 +260,22 @@ class CharacterAnimButton extends UIButton {
if (newAnim == animData.anim) return; if (newAnim == animData.anim) return;
animData.anim = newAnim; animData.anim = newAnim;
if (parent.character.animateAtlas != null) {
var animSymbol:FlxSymbolAnimation = parent.character.animateAtlas.anim.animsMap[anim]; if (parent.character.animateAtlas != null)
refreshSymbolKeyFrames(animSymbol, animData); __refreshAnimation();
} else { else {
var flxAnimation:FlxAnimation = parent.character.animation._animations[anim]; var flxAnimation:FlxAnimation = __getFlxAnimation();
trace(parent.character.animation._animations);
flxAnimation.prefix = newAnim; flxAnimation.prefix = newAnim;
refreshFlxAnimationFrames(flxAnimation, animData); refreshFlxAnimationFrames(flxAnimation, animData);
parent.buildAnimDisplay(anim, flxAnimation); if (valid) {
parent.buildAnimDisplay(anim, flxAnimation);
animationDisplayBG.alpha = 1;
} else {
parent.removeAnimDisplay(anim);
animationDisplayBG.alpha = 0.4;
}
} }
if (parent.character.getAnimName() == anim) if (parent.character.getAnimName() == anim)
@@ -280,7 +296,7 @@ class CharacterAnimButton extends UIButton {
if (parent.character.getAnimName() == anim) if (parent.character.getAnimName() == anim)
CharacterEditor.instance.playAnimation(anim); CharacterEditor.instance.playAnimation(anim);
field.text = '${animData.name} (${positionXStepper.value = animData.x}, ${positionYStepper.value = animData.y})'; updateText();
} }
public function changeFPS(newFPS:Float) @:privateAccess { public function changeFPS(newFPS:Float) @:privateAccess {
@@ -288,10 +304,10 @@ class CharacterAnimButton extends UIButton {
animData.fps = newFPS; animData.fps = newFPS;
if (parent.character.animateAtlas != null) { if (parent.character.animateAtlas != null) {
var animSymbol:FlxSymbolAnimation = parent.character.animateAtlas.anim.animsMap[anim]; var animSymbol:FlxSymbolAnimation = __getAnimationSymbol();
animSymbol.frameRate = newFPS; animSymbol.frameRate = newFPS;
} else { } else {
var flxAnimation:FlxAnimation = parent.character.animation._animations[anim]; var flxAnimation:FlxAnimation = __getFlxAnimation();
flxAnimation.frameRate = newFPS; flxAnimation.frameRate = newFPS;
} }
@@ -304,10 +320,10 @@ class CharacterAnimButton extends UIButton {
animData.loop = newLooping; animData.loop = newLooping;
if (parent.character.animateAtlas != null) { if (parent.character.animateAtlas != null) {
var animSymbol:FlxSymbolAnimation = parent.character.animateAtlas.anim.animsMap[anim]; var animSymbol:FlxSymbolAnimation = __getAnimationSymbol();
animSymbol.instance.symbol.loop = animData.loop ? Loop : PlayOnce; animSymbol.instance.symbol.loop = animData.loop ? Loop : PlayOnce;
} else { } else {
var flxAnimation:FlxAnimation = parent.character.animation._animations[anim]; var flxAnimation:FlxAnimation = __getFlxAnimation();
flxAnimation.looped = animData.loop; flxAnimation.looped = animData.loop;
} }
@@ -319,13 +335,7 @@ class CharacterAnimButton extends UIButton {
var animData:AnimData = parent.character.animDatas[anim]; var animData:AnimData = parent.character.animDatas[anim];
animData.indices = indicies; animData.indices = indicies;
if (parent.character.animateAtlas != null) { __refreshAnimation();
var animSymbol:FlxSymbolAnimation = parent.character.animateAtlas.anim.animsMap[anim];
refreshSymbolKeyFrames(animSymbol, animData);
} else {
var flxAnimation:FlxAnimation = parent.character.animation._animations[anim];
refreshFlxAnimationFrames(flxAnimation, animData);
}
if (parent.character.getAnimName() == anim) if (parent.character.getAnimName() == anim)
CharacterEditor.instance.playAnimation(anim); CharacterEditor.instance.playAnimation(anim);
@@ -347,23 +357,38 @@ class CharacterAnimButton extends UIButton {
flxAnimation.frames = frameIndices; flxAnimation.frames = frameIndices;
} }
if (flxAnimation.frames.length <= 0) invalidate();
else validate();
} catch (e) { } catch (e) {
trace('TODO: ERROR HANDLING $e'); trace('$e');
invalidate();
} }
} }
public inline function refreshSymbolKeyFrames(symbol:FlxSymbolAnimation, animData:AnimData) @:privateAccess { public inline function refreshSymbolKeyFrames(symbol:FlxSymbolAnimation, animData:AnimData) @:privateAccess {
if (animData.indices.length > 0) { var wasRefreshed:Bool = false;
// keeps on crashing, look at flxanimate FlxAnim.hx for refrence
} else { try {
for (name in parent.character.animateAtlas.anim.symbolDictionary.keys()) if (animData.indices.length > 0) {
if (parent.character.animateAtlas.anim.startsWith(name, animData.anim)) // keeps on crashing, look at flxanimate FlxAnim.hx for refrence
{symbol.instance.symbol.name = name; break;} } else {
for (name in parent.character.animateAtlas.anim.symbolDictionary.keys())
if (parent.character.animateAtlas.anim.startsWith(name, animData.anim)) {
symbol.instance.symbol.name = name;
wasRefreshed = true;
break;
}
}
} catch (e) {
trace('$e');
} }
validate(wasRefreshed);
} }
public function toggleGhost() { public function toggleGhost() {
if (parent.ghosts.indexOf(anim) == -1) { if (valid && parent.ghosts.indexOf(anim) == -1) {
parent.ghosts.push(anim); parent.ghosts.push(anim);
ghostIcon.animation.play("alive", true); ghostIcon.animation.play("alive", true);
ghostIcon.color = 0xFFFFFFFF; ghostIcon.color = 0xFFFFFFFF;
@@ -392,4 +417,55 @@ class CharacterAnimButton extends UIButton {
parent.displayWindowSprite.draw(); parent.displayWindowSprite.draw();
} }
} }
public function updateText() {
field.applyMarkup(
'${anim} ' + (valid ? '(${parent.character.animOffsets[anim].x} ${parent.character.animOffsets[anim].y})' : "|(Invalid Animation!!!)|"),
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFF29797), "|")]);
}
public function validate(isValid:Bool = true) {
var wasValid:Bool = valid;
this.valid = isValid;
animIcon.animation.play(valid ? "play" :"error");
color = valid ? 0xFFFFFFFF : 0xFFD60E0E;
ghostIcon.visible = ghostButton.visible = isValid;
XYComma.alpha = isValid ? 1 : 0.4;
for (uiElement in [nameTextBox, positionXStepper, positionYStepper, fpsStepper, loopedCheckbox, indicesTextBox]) {
uiElement.selectable = isValid;
if (labels[uiElement] != null)
labels[uiElement].alpha = isValid ? 1 : 0.4;
}
if (!valid) toggleGhost();
updateText();
if (!wasValid && isValid && CharacterEditor.instance.characterFakeAnim == anim)
CharacterEditor.instance.playAnimation(this.anim);
}
public inline function invalidate()
validate(false);
public inline function __getFlxAnimation():Null<FlxAnimation> @:privateAccess {
if (parent.character.animation._animations[anim] == null)
XMLUtil.addAnimToSprite(parent.character, data);
return parent.character.animation._animations[anim];
}
public inline function __getAnimationSymbol():Null<FlxSymbolAnimation> @:privateAccess {
if (parent.character.animateAtlas.anim.animsMap[anim] == null)
XMLUtil.addAnimToSprite(parent.character, data);
return parent.character.animateAtlas.anim.animsMap[anim];
}
@:noCompletion function __refreshAnimation() @:privateAccess {
if (parent.character.animateAtlas != null) refreshSymbolKeyFrames(__getAnimationSymbol(), data);
else refreshFlxAnimationFrames(__getFlxAnimation(), data);
}
public inline function checkValid()
__refreshAnimation();
} }
@@ -52,6 +52,8 @@ class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
} }
public function buildAnimDisplay(name:String, anim:FlxAnimation) { public function buildAnimDisplay(name:String, anim:FlxAnimation) {
if (anim.frames.length <= 0) return;
var frameIndex:Int = anim.frames.getDefault([0])[0]; var frameIndex:Int = anim.frames.getDefault([0])[0];
var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex]; var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex];
@@ -61,6 +63,9 @@ class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
displayAnimsFramesList.set(name, {frame: anim.frames.getDefault([0])[0], scale: 104/animBounds.height, animBounds: animBounds}); displayAnimsFramesList.set(name, {frame: anim.frames.getDefault([0])[0], scale: 104/animBounds.height, animBounds: animBounds});
} }
public function removeAnimDisplay(name:String)
displayAnimsFramesList.remove(name);
public function deleteAnimation(button:CharacterAnimButton) { public function deleteAnimation(button:CharacterAnimButton) {
if (buttons.members.length <= 1) return; if (buttons.members.length <= 1) return;
if (character.getAnimName() == button.anim) if (character.getAnimName() == button.anim)
@@ -95,13 +100,21 @@ class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
} }
public function addAnimation(animData:AnimData, animID:Int = -1) @:privateAccess { public function addAnimation(animData:AnimData, animID:Int = -1) @:privateAccess {
XMLUtil.addAnimToSprite(character, animData);
buildAnimDisplay(animData.name, character.animation._animations[animData.name]);
var newButton:CharacterAnimButton = new CharacterAnimButton(0, 0, animData, this); var newButton:CharacterAnimButton = new CharacterAnimButton(0, 0, animData, this);
newButton.alpha = 0.25; animButtons.set(animData.name, newButton); newButton.alpha = 0.25; animButtons.set(animData.name, newButton);
if (animID == -1) add(newButton); if (animID == -1) add(newButton);
else insert(newButton, animID); else insert(newButton, animID);
if (newButton.valid) {
XMLUtil.addAnimToSprite(character, animData);
buildAnimDisplay(animData.name, character.animation._animations[animData.name]);
}
}
public function findValid():Null<String> {
for (button in buttons)
if (button.valid) return button.anim;
return null;
} }
} }
@@ -684,20 +684,32 @@ class CharacterEditor extends UIState {
playAnimation( playAnimation(
characterAnimsWindow.animsList[ characterAnimsWindow.animsList[
FlxMath.wrap( FlxMath.wrap(
characterAnimsWindow.animsList.indexOf(character.getAnimName()) - 1, characterAnimsWindow.animsList.indexOf(characterFakeAnim) - 1,
0, characterAnimsWindow.animsList.length-1 0, characterAnimsWindow.animsList.length-1
)] )]
); );
function _animation_down(_) function _animation_down(_)
playAnimation( playAnimation(
characterAnimsWindow.animsList[FlxMath.wrap( characterAnimsWindow.animsList[FlxMath.wrap(
characterAnimsWindow.animsList.indexOf(character.getAnimName()) + 1, characterAnimsWindow.animsList.indexOf(characterFakeAnim) + 1,
0, characterAnimsWindow.animsList.length-1 0, characterAnimsWindow.animsList.length-1
)] )]
); );
// The animation thats playing regardless if its valid or not
public var characterFakeAnim:String = "";
public function playAnimation(anim:String) { public function playAnimation(anim:String) {
character.playAnim(anim, true); characterFakeAnim = anim;
if (characterAnimsWindow.animButtons[anim] != null && characterAnimsWindow.animButtons[anim].valid) {
character.playAnim(anim, true);
character.colorTransform.redMultiplier = character.colorTransform.greenMultiplier = character.colorTransform.blueMultiplier = character.colorTransform.alphaMultiplier = 1;
character.colorTransform.redOffset = character.colorTransform.greenOffset = character.colorTransform.blueOffset = character.colorTransform.alphaOffset = 0;
} else {
var validAnimation:String = characterAnimsWindow.findValid();
if (validAnimation != null) character.playAnim(validAnimation, true);
_animation_stop(null);
character.colorTransform.color = 0xFFEF0202;
}
for(i in characterAnimsWindow.buttons.members) for(i in characterAnimsWindow.buttons.members)
i.alpha = i.anim == anim ? 1 : 0.25; i.alpha = i.anim == anim ? 1 : 0.25;
@@ -1,5 +1,6 @@
package funkin.editors.character; package funkin.editors.character;
import openfl.geom.ColorTransform;
import flixel.animation.FlxAnimation; import flixel.animation.FlxAnimation;
import funkin.game.Character; import funkin.game.Character;
+3 -2
View File
@@ -29,10 +29,11 @@ class UICheckbox extends UISprite {
public override function update(elapsed:Float) { public override function update(elapsed:Float) {
// ANIMATION HANDLING // ANIMATION HANDLING
animation.play(hovered ? (pressed ? "pressed" : "hover") : "normal"); animation.play(hovered && selectable ? (pressed ? "pressed" : "hover") : "normal");
this.alpha = field.alpha = selectable ? 1 : 0.4;
// CHECKMARK HANDLING // CHECKMARK HANDLING
check.alpha = checked ? 1 : 0; check.alpha = selectable ? (checked ? 1 : 0) : 0;
check.scale.x = CoolUtil.fpsLerp(check.scale.x, 1, 0.25); check.scale.x = CoolUtil.fpsLerp(check.scale.x, 1, 0.25);
check.scale.y = CoolUtil.fpsLerp(check.scale.y, 1, 0.25); check.scale.y = CoolUtil.fpsLerp(check.scale.y, 1, 0.25);