diff --git a/source/funkin/editors/character/CharacterEditor.hx b/source/funkin/editors/character/CharacterEditor.hx index 258bf8ff..b5647849 100644 --- a/source/funkin/editors/character/CharacterEditor.hx +++ b/source/funkin/editors/character/CharacterEditor.hx @@ -16,6 +16,9 @@ import funkin.editors.ui.UIContextMenu.UIContextMenuOptionSpr; import funkin.game.Character; import haxe.xml.Access; import haxe.xml.Printer; +import funkin.editors.ui.UIImageExplorer.ImageSaveData; +import sys.FileSystem; +import sys.io.File; class CharacterEditor extends UIState { static var __character:String; @@ -505,6 +508,20 @@ class CharacterEditor extends UIState { changeCharacterDesginedAs(!newIsPlayer, false); case CCharEditInfo(oldInfo, newInfo): characterPropertiesWindow.editCharacterInfo(oldInfo, false); + case CCharEditSprite(fileID): + var cneisdPath:String = './.temp/__undo__${Type.getClassName(Type.getClass(FlxG.state))}__${fileID}.cneisd'; + if (FileSystem.exists(cneisdPath)) { + try { + var cneisdData:String = File.getContent(cneisdPath); + var imageSaveData:ImageSaveData = UIImageExplorer.deserializeSaveDataGlobal(cneisdData); + + UIImageExplorer.saveFilesGlobal(imageSaveData, '${Paths.getAssetsRoot()}/images/characters', () -> { + characterPropertiesWindow.changeSprite(imageSaveData.imageName); + }, false); + } catch (e) { + trace('ERROR COMPLETING UNDO: $e'); + }; + } case CAnimCreate(animID, animData): characterAnimsWindow.deleteAnimation(characterAnimsWindow.buttons.members[animID], false); case CAnimDelete(animID, animData): @@ -544,8 +561,8 @@ class CharacterEditor extends UIState { _undo(undos.undo()); } - function _redo(undo:CharacterEditorChange) { - switch (undo) { + function _redo(redo:CharacterEditorChange) { + switch (redo) { case null: // do nothing case CCharEditPosition(oldPos, newPos): characterPropertiesWindow.changePosition(newPos.x, newPos.y, false); @@ -561,6 +578,20 @@ class CharacterEditor extends UIState { changeCharacterDesginedAs(newIsPlayer, false); case CCharEditInfo(oldInfo, newInfo): characterPropertiesWindow.editCharacterInfo(newInfo, false); + case CCharEditSprite(fileID): + var cneisdPath:String = './.temp/__redo__${Type.getClassName(Type.getClass(FlxG.state))}__${fileID}.cneisd'; + if (FileSystem.exists(cneisdPath)) { + try { + var cneisdData:String = File.getContent(cneisdPath); + var imageSaveData:ImageSaveData = UIImageExplorer.deserializeSaveDataGlobal(cneisdData); + + UIImageExplorer.saveFilesGlobal(imageSaveData, '${Paths.getAssetsRoot()}/images/characters', () -> { + characterPropertiesWindow.changeSprite(imageSaveData.imageName); + }, false); + } catch (e) { + trace('ERROR COMPLETING UNDO: $e'); + }; + } case CAnimCreate(animID, animData): characterAnimsWindow.addAnimation(animData, animID, false); playAnimation(animData.name); @@ -629,16 +660,16 @@ class CharacterEditor extends UIState { } function _change_offset(x:Float, y:Float) { - if (character.getAnimName() == null) return; + if (characterFakeAnim == null) return; _set_offset( - character.animOffsets[character.getAnimName()].x - x, - character.animOffsets[character.getAnimName()].y - y + character.animOffsets[characterFakeAnim].x - x, + character.animOffsets[characterFakeAnim].y - y ); } function _set_offset(x:Float, y:Float) { - if (character.getAnimName() == null) return; - characterAnimsWindow.animButtons.get(character.getAnimName()).changeOffset( + if (characterAnimsWindow.animButtons[characterFakeAnim] == null || !characterAnimsWindow.animButtons[characterFakeAnim].valid) return; + characterAnimsWindow.animButtons.get(characterFakeAnim).changeOffset( FlxMath.roundDecimal(x, 2), FlxMath.roundDecimal(y, 2) ); } @@ -883,6 +914,7 @@ enum CharacterEditorChange { CCharEditDesignedAs(newIsPlayer:Bool); CCharEditInfo(oldInfo:CharacterExtraInfo, newInfo:CharacterExtraInfo); + CCharEditSprite(fileID:Int); CAnimCreate(animID:Int, animData:AnimData); CAnimDelete(animID:Int, animData:AnimData); diff --git a/source/funkin/editors/character/CharacterSpriteScreen.hx b/source/funkin/editors/character/CharacterSpriteScreen.hx index 294cfc2e..cdf2f7ee 100644 --- a/source/funkin/editors/character/CharacterSpriteScreen.hx +++ b/source/funkin/editors/character/CharacterSpriteScreen.hx @@ -3,13 +3,14 @@ package funkin.editors.character; import haxe.io.Bytes; import flixel.util.typeLimit.OneOfTwo; import flixel.text.FlxText.FlxTextFormat; +import funkin.editors.ui.UIImageExplorer.ImageSaveData; import flixel.text.FlxText.FlxTextFormatMarkerPair; class CharacterSpriteScreen extends UISubstateWindow { private var imagePath:String = null; private var onSave:(String, Bool) -> Void = null; - public var ogImageFiles:Map> = []; + public var ogImageSaveData:ImageSaveData; public var imageExplorer:UIImageExplorer; public var saveButton:UIButton; @@ -39,9 +40,10 @@ class CharacterSpriteScreen extends UISubstateWindow { "Character Image File $* Required$", [new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]); - ogImageFiles = imageExplorer.imageFiles.copy(); + ogImageSaveData = imageExplorer.getSaveData(); saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, windowSpr.y + windowSpr.bHeight - 20, "Save & Close", function() { + addToUndo(); // should be async?? -lunar imageExplorer.saveFiles('${Paths.getAssetsRoot()}/images/characters', () -> { onSave(imageExplorer.imageName, imageExplorer.isAtlas); close(); @@ -67,7 +69,7 @@ class CharacterSpriteScreen extends UISubstateWindow { refreshWindowSize(); if (imageExplorer == null || imageExplorer.imageFiles == null) return; - var filesSame = CoolUtil.deepEqual(ogImageFiles, imageExplorer.imageFiles); + var filesSame = CoolUtil.deepEqual(ogImageSaveData.imageFiles, imageExplorer.imageFiles); saveButton.selectable = !filesSame && !CoolUtil.isMapEmpty(imageExplorer.imageFiles) && (imageExplorer.animationList.length > 0); } @@ -80,4 +82,13 @@ class CharacterSpriteScreen extends UISubstateWindow { closeButton.x = saveButton.x - 20 - closeButton.bWidth; closeButton.y = saveButton.y = imageExplorer.y + imageExplorer.bHeight + 14; } + + public static var idCounter:Int = -1; + public inline function addToUndo() { + idCounter = FlxMath.wrap(idCounter + FlxG.random.int(1, 57349), 0, 9999); + CharacterEditor.undos.addToUndo(CCharEditSprite(idCounter)); + + CoolUtil.safeSaveFile('./.temp/__undo__${Type.getClassName(Type.getClass(FlxG.state))}__${idCounter}.cneisd', UIImageExplorer.serializeSaveDataGlobal(ogImageSaveData)); + CoolUtil.safeSaveFile('./.temp/__redo__${Type.getClassName(Type.getClass(FlxG.state))}__${idCounter}.cneisd', UIImageExplorer.serializeSaveDataGlobal(imageExplorer.getSaveData())); + } } \ No newline at end of file diff --git a/source/funkin/editors/ui/UIImageExplorer.hx b/source/funkin/editors/ui/UIImageExplorer.hx index 2b5d817e..8101e2ce 100644 --- a/source/funkin/editors/ui/UIImageExplorer.hx +++ b/source/funkin/editors/ui/UIImageExplorer.hx @@ -247,7 +247,7 @@ class UIImageExplorer extends UIFileExplorer { return { imageName: this.imageName, isAtlas: this.isAtlas, - imageFiles: this.imageFiles + imageFiles: this.imageFiles.copy() }; } @@ -255,6 +255,12 @@ class UIImageExplorer extends UIFileExplorer { UIImageExplorer.saveFilesGlobal(getSaveData(), directory, onFinishSaving, checkExisting); } + public static function serializeSaveDataGlobal(data:ImageSaveData):String + return haxe.Serializer.run(data); + + public static function deserializeSaveDataGlobal(data:String):ImageSaveData + return cast haxe.Unserializer.run(data); + public static function saveFilesGlobal(imageData:ImageSaveData, directory:String, ?onFinishSaving:Void->Void, ?checkExisting:Bool = true) { if (imageData.isAtlas) directory += '/${imageData.imageName}';