package funkin.editors.character; import funkin.backend.utils.XMLUtil.AnimData; import flixel.animation.FlxAnimation; import flixel.graphics.FlxGraphic; import openfl.geom.Rectangle; import flixel.graphics.frames.FlxFrame; import funkin.game.Character; using funkin.backend.utils.BitmapUtil; class CharacterAnimsWindow extends UIButtonList { public var character:CharacterGhost; public var displayWindowSprite:FlxSprite; public var displayWindowGraphic:FlxGraphic; public var displayAnimsFramesList:Map = []; public var animButtons:Map = []; public var animsList:Array = []; public function new(x:Float, y:Float, character:CharacterGhost) { super(x, y, Std.int(500-16), 419, null, FlxPoint.get(Std.int(500-16-32), 208)); this.character = character; cameraSpacing = 0; frames = Paths.getFrames('editors/ui/inputbox'); buttonCameras.pixelPerfectRender = true; if (Assets.exists(Paths.image('characters/${character.sprite}'))) displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false)); displayWindowSprite = new FlxSprite(); displayWindowSprite.loadGraphicFromSprite(character); displayWindowSprite.antialiasing = character.antialiasing; displayWindowSprite.flipX = character.flipX; alpha = 0.7; for (anim in character.getAnimOrder()) addAnimation(character.animDatas.get(anim)); addButton.callback = generateAnimation; } public var ghosts:Array = []; public override function update(elapsed:Float) { super.update(elapsed); animsList = [for (button in buttons) button.anim]; character.ghosts = ghosts; } public function buildAnimDisplay(name:String, anim:FlxAnimation) { if (anim.frames.length <= 0) return; 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: anim.frames.getDefault([0])[0], scale: 104/animBounds.height, animBounds: animBounds}); } public function removeAnimDisplay(name:String) displayAnimsFramesList.remove(name); public function deleteAnimation(button:CharacterAnimButton) { if (buttons.members.length <= 1) return; if (character.getAnimName() == button.anim) @:privateAccess CharacterEditor.instance._animation_down(null); character.removeAnimation(button.anim); if (character.animOffsets.exists(button.anim)) character.animOffsets.remove(button.anim); if (character.animDatas.exists(button.anim)) character.animDatas.remove(button.anim); remove(button); button.destroy(); } public function generateAnimation() { var animName:String = "New Anim"; var animNames:Array = character.getNameList(); var newAnimCount:Int = 0; while (animNames.indexOf(animName) != -1) { newAnimCount++; animName = 'New Anim - $newAnimCount'; } var animData:AnimData = { name: animName, anim: character.frames.getByIndex(0).name, fps: 24, loop: false, x: 0, y: 0, indices: [], animType: NONE, }; addAnimation(animData); } public function addAnimation(animData:AnimData, animID:Int = -1) @:privateAccess { var newButton:CharacterAnimButton = new CharacterAnimButton(0, 0, animData, this); newButton.alpha = 0.25; animButtons.set(animData.name, newButton); if (animID == -1) add(newButton); else insert(newButton, animID); if (newButton.valid) { XMLUtil.addAnimToSprite(character, animData); if (character.animation._animations[animData.name] != null) buildAnimDisplay(animData.name, character.animation._animations[animData.name]); } } public function findValid():Null { for (button in buttons) if (button.valid) return button.anim; return null; } }