Animate Atlas character editor previews

This commit is contained in:
Yoshman29
2026-01-21 18:20:39 +01:00
parent 9d2fd9dc20
commit ae89e0259a
5 changed files with 52 additions and 17 deletions
+2 -1
View File
@@ -332,8 +332,9 @@ class Flags {
if (!(parsed = parse(name, value))) customFlags.set(name, value);
if (!overridenFlags.exists(name)) overridenFlags.set(name, parsed);
}
#if MODCHARTING_FEATURES
Options.modchartingHoldSubdivisions = DEFAULT_MODCHART_HOLD_SUBDIVISIONS;
#end
}
/**
@@ -8,6 +8,7 @@ import openfl.geom.Rectangle;
import funkin.backend.utils.XMLUtil.AnimData;
import flixel.math.FlxPoint;
import flixel.util.FlxColor;
import funkin.editors.character.CharacterAnimsWindow;
using StringTools;
@@ -242,7 +243,7 @@ class CharacterAnimButton extends UIButton {
parent.character.animOffsets.remove(anim);
parent.character.animOffsets.set(newName, animOffset);
var displayFrame:{scale:Float, animBounds:Rectangle, frame:Int} = parent.displayAnimsFramesList[anim];
var displayFrame:DisplayAnimFrameEntry = parent.displayAnimsFramesList[anim];
parent.displayAnimsFramesList.remove(anim);
parent.displayAnimsFramesList.set(newName, displayFrame);
@@ -396,12 +397,9 @@ class CharacterAnimButton extends UIButton {
updateButtonsPos();
super.draw();
if (parent.character.isAnimate) // TODO: displayWindowSprite for atlases
return;
if (!closed && parent.displayAnimsFramesList.exists(anim)) {
var displayData:{frame:Int, scale:Float, animBounds:Rectangle} = parent.displayAnimsFramesList.get(anim);
parent.displayWindowSprite.frame = parent.displayWindowSprite.frames.frames[displayData.frame];
var displayData:DisplayAnimFrameEntry = parent.displayAnimsFramesList.get(anim);
parent.displayWindowSprite.frame = displayData.frame;
parent.displayWindowSprite.scale.x = parent.displayWindowSprite.scale.y = displayData.scale;
parent.displayWindowSprite.updateHitbox();
@@ -476,7 +474,6 @@ class CharacterAnimButton extends UIButton {
@:noCompletion function __refreshAnimation() @:privateAccess {
refreshAnimation(__getFlxAnimation(), data);
// TODO: displayWindowSprite for atlases
if (valid) {
parent.buildAnimDisplay(anim, data);
animationDisplayBG.alpha = 1;
@@ -8,15 +8,24 @@ import openfl.geom.Rectangle;
import flixel.graphics.frames.FlxFrame;
import funkin.game.Character;
import flixel.animation.FlxPrerotatedAnimation;
import animate.internal.RenderTexture;
import flixel.graphics.frames.FlxFrame;
import funkin.backend.system.Logs;
using funkin.backend.utils.BitmapUtil;
typedef DisplayAnimFrameEntry = {
scale:Float,
frame:FlxFrame,
renderTexture:RenderTexture
}
class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
public var character:CharacterGhost;
public var displayWindowSprite:FlxSprite;
public var displayWindowGraphic:FlxGraphic;
public var displayAnimsFramesList:Map<String, {scale:Float, animBounds:Rectangle, frame:OneOfTwo<Int, String>}> = [];
public var displayAnimsFramesList:Map<String, DisplayAnimFrameEntry> = [];
public var animButtons:Map<String, CharacterAnimButton> = [];
public var animsList:Array<String> = [];
@@ -70,22 +79,47 @@ class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
public function buildAnimDisplay(name:String, anim:AnimData) @:privateAccess {
var anim:FlxAnimation = character.animation._animations[anim.name];
if (anim == null || anim.frames.length <= 0) return;
if (anim == null) return;
var frameIndex:Int = anim.frames.getDefault([0])[0];
var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex];
if (character.isAnimate) {
var renderTex = character.generateRenderTextureForAnim(name);
var frame = renderTex.graphic.imageFrame.frame;
var frameRect:Rectangle = new Rectangle(frame.offset.x, frame.offset.y, frame.sourceSize.x, frame.sourceSize.y);
var animBounds:Rectangle = displayWindowGraphic != null ? displayWindowGraphic.bitmap.bounds(frameRect) : frameRect;
trace('Created anim display for ${name} with size ${frame.frame.width}, ${frame.frame.height} (${renderTex.graphic.width}, ${renderTex.graphic.height})');
displayAnimsFramesList.set(name, {
frame: frame,
scale: 104/Math.max(frame.frame.width, frame.frame.height),
renderTexture: renderTex
});
} else {
var frameIndex:Int = anim.frames.getDefault([0])[0];
var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex];
var frameRect:Rectangle = new Rectangle(frame.offset.x, frame.offset.y, frame.sourceSize.x, frame.sourceSize.y);
var animBounds:Rectangle = displayWindowGraphic != null ? displayWindowGraphic.bitmap.bounds(frameRect) : frameRect;
displayAnimsFramesList.set(name, {
frame: character.frames.frames[anim.frames.getDefault([0])[0]],
scale: 104/Math.max(animBounds.width, animBounds.height),
renderTexture: null
});
}
displayAnimsFramesList.set(name, {frame: anim.frames.getDefault([0])[0], scale: 104/Math.max(animBounds.width, animBounds.height), animBounds: animBounds});
}
public function removeAnimDisplay(name:String) {
if (displayAnimsFramesList.exists(name))
displayAnimsFramesList[name].renderTexture?.destroy();
displayAnimsFramesList.remove(name);
}
public function clearDisplayAnims() {
for(k=>e in displayAnimsFramesList)
e.renderTexture?.destroy();
displayAnimsFramesList.clear();
}
public function deleteAnimation(button:CharacterAnimButton, addToUndo:Bool = true) {
FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_DELETE_SOUND));
if (buttons.members.length <= 1) return;
@@ -84,9 +84,11 @@ class CharacterGhost extends Character {
var oldRenderTexture:RenderTexture = this._renderTexture;
var oldRenderTextureDirty = _renderTextureDirty;
var oldAlpha = alpha;
this._renderTexture = null;
this._renderTextureDirty = true;
this.alpha = 256.0/257.0;
animation.play(anim, true, false, 0);
@@ -96,6 +98,7 @@ class CharacterGhost extends Character {
this._renderTexture = oldRenderTexture;
this._renderTextureDirty = oldRenderTextureDirty;
this.alpha = oldAlpha;
if (wasInvalidFrame) {
colorTransform.color = 0xFFEF0202;
@@ -183,7 +183,7 @@ class CharacterPropertiesWindow extends UISliceSprite {
character.sprite = sprite;
animsWindow.displayWindowSprite.animation.reset();
animsWindow.displayAnimsFramesList.clear();
animsWindow.clearDisplayAnims();
if (animsWindow.displayWindowGraphic != null)
animsWindow.displayWindowGraphic.destroy();