package funkin.editors.character; import flixel.util.typeLimit.OneOfTwo; 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}')) && character.animateAtlas == null) 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; setAnimAutoComplete(CoolUtil.getAnimsListFromSprite(character)); } 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:AnimData) @:privateAccess { if (character.animateAtlas == null) { var anim:FlxAnimation = character.animation._animations[anim.name]; if (anim == null || 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}); } else { character.storeAtlasState(); /* character.animateAtlas.anim.play(anim.name, true, false, 0); character.animateAtlas.anim.stop(); var animBounds:Rectangle = MatrixUtil.getBounds(character).copyToFlash(); displayAnimsFramesList.set(name, {frame: anim.anim, scale: 104/animBounds.height, animBounds: animBounds}); */ character.restoreAtlasState(); } } 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); buildAnimDisplay(animData.name, animData); } } public inline function setAnimAutoComplete(anims:Array) { for (button in buttons) button.animTextBox.suggestItems = anims; } public function findValid():Null { for (button in buttons) if (button.valid) return button.anim; return null; } }