From c113333bd1ad4945af5f31368c0e88f3a2980467 Mon Sep 17 00:00:00 2001 From: Kolo <67389779+KoloInDaCrib@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:01:02 +0100 Subject: [PATCH] more works on ghost + small bug fixed --- .../ui/debug/char/CharCreatorCharacter.hx | 16 ++++ .../funkin/ui/debug/char/CharCreatorState.hx | 1 + .../char/components/dialogs/AddAnimDialog.hx | 10 ++- .../components/dialogs/GhostSettingsDialog.hx | 56 +++++++++---- .../components/wizard/AddCharFilesDialog.hx | 75 ++++++----------- .../components/wizard/DefaultWizardDialog.hx | 2 + source/funkin/ui/debug/char/import.hx | 3 +- .../char/pages/CharCreatorGameplayPage.hx | 80 +++++++++++++------ source/funkin/ui/debug/char/util/GhostUtil.hx | 64 ++++++++++++++- 9 files changed, 206 insertions(+), 101 deletions(-) diff --git a/source/funkin/ui/debug/char/CharCreatorCharacter.hx b/source/funkin/ui/debug/char/CharCreatorCharacter.hx index dbe5137058..f2840052ab 100644 --- a/source/funkin/ui/debug/char/CharCreatorCharacter.hx +++ b/source/funkin/ui/debug/char/CharCreatorCharacter.hx @@ -148,9 +148,25 @@ class CharCreatorCharacter extends Bopper offsets: offsets }); + super.setAnimationOffsets(name, offsets[0], offsets[1]); + return true; } + override public function setAnimationOffsets(name:String, xOffset:Float, yOffset:Float) + { + super.setAnimationOffsets(name, xOffset, yOffset); + + for (anim in animations) + { + if (anim.name == name) + { + anim.offsets = [xOffset, yOffset]; + break; + } + } + } + public override function playAnimation(name:String, restart:Bool = false, ignoreOther:Bool = false, reverse:Bool = false):Void { if (atlasCharacter == null) diff --git a/source/funkin/ui/debug/char/CharCreatorState.hx b/source/funkin/ui/debug/char/CharCreatorState.hx index 475f965137..b626c4be95 100644 --- a/source/funkin/ui/debug/char/CharCreatorState.hx +++ b/source/funkin/ui/debug/char/CharCreatorState.hx @@ -15,6 +15,7 @@ import flixel.FlxG; /** * also made by kolo + * in collaboration with lemz! * my second slightly more disappointing son */ @:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/char-creator/main-view.xml")) diff --git a/source/funkin/ui/debug/char/components/dialogs/AddAnimDialog.hx b/source/funkin/ui/debug/char/components/dialogs/AddAnimDialog.hx index 12d42dbb37..3d54441ef6 100644 --- a/source/funkin/ui/debug/char/components/dialogs/AddAnimDialog.hx +++ b/source/funkin/ui/debug/char/components/dialogs/AddAnimDialog.hx @@ -1,5 +1,6 @@ package funkin.ui.debug.char.components.dialogs; +import funkin.ui.debug.char.pages.CharCreatorGameplayPage.CharDialogType; import haxe.ui.containers.dialogs.CollapsibleDialog; import haxe.ui.data.ArrayDataSource; @@ -76,10 +77,12 @@ class AddAnimDialog extends DefaultPageDialog charAnimFlipY.selected); if (!animAdded) return; - - char.setAnimationOffsets(charAnimName.text, charAnimOffsetX.pos, charAnimOffsetY.pos); char.playAnimation(charAnimName.text); + cast(page, CharCreatorGameplayPage).ghostCharacter.addAnimation(charAnimName.text, charAnimPrefix.text, [charAnimOffsetX.pos, charAnimOffsetY.pos], + (shouldDoIndices ? indices : []), charAnimPath.text, Std.int(charAnimFramerate.pos), charAnimLooped.selected, charAnimFlipX.selected, + charAnimFlipY.selected); + updateDropdown(); charAnimDropdown.selectedIndex = charAnimDropdown.dataSource.size - 1; } @@ -91,5 +94,8 @@ class AddAnimDialog extends DefaultPageDialog for (anim in linkedChar.animations) charAnimDropdown.dataSource.add({text: anim.name}); + + var gameplayPage = cast(page, CharCreatorGameplayPage); + if (gameplayPage.ghostId == "") gameplayPage.refreshGhoulAnims(); } } diff --git a/source/funkin/ui/debug/char/components/dialogs/GhostSettingsDialog.hx b/source/funkin/ui/debug/char/components/dialogs/GhostSettingsDialog.hx index 82e5556308..90c829e539 100644 --- a/source/funkin/ui/debug/char/components/dialogs/GhostSettingsDialog.hx +++ b/source/funkin/ui/debug/char/components/dialogs/GhostSettingsDialog.hx @@ -12,23 +12,42 @@ import flixel.tweens.FlxTween; @:build(haxe.ui.macros.ComponentMacros.build("assets/exclude/data/ui/char-creator/dialogs/ghost-dialog.xml")) class GhostSettingsDialog extends DefaultPageDialog { - var attachedMenu:GhostCharacterMenu; + public var attachedMenu:GhostCharacterMenu; + public var charId:String = Constants.DEFAULT_CHARACTER; override public function new(daPage:CharCreatorDefaultPage) { super(daPage); - + var regularChar = cast(daPage, CharCreatorGameplayPage).currentCharacter; + var ghostChar = cast(daPage, CharCreatorGameplayPage).ghostCharacter; var charData = CharacterDataParser.fetchCharacterData(Constants.DEFAULT_CHARACTER); + ghostTypeButton.icon = (charData == null ? null : CharacterDataParser.getCharPixelIconAsset(Constants.DEFAULT_CHARACTER)); ghostTypeButton.text = (charData == null ? "None" : charData.name.length > 6 ? '${charData.name.substr(0, 6)}.' : '${charData.name}'); // callbacks ghostEnable.onChange = function(_) { ghostDataBox.disabled = !ghostEnable.selected; + ghostChar.visible = ghostEnable.selected; + + if (ghostChar.visible) // i love saving on data + { + cast(daPage, CharCreatorGameplayPage).ghostId = (ghostCustomChar.selected ? charId : ""); + } } ghostCurChar.onChange = function(_) { - ghostTypeButton.disabled = ghostCurChar.selected; // no need to check for the other one thankfully + ghostTypeButton.disabled = ghostCurChar.selected; + if (ghostCurChar.selected) Screen.instance.removeComponent(attachedMenu); + + if (ghostChar.visible && ghostCurChar.selected) cast(daPage, CharCreatorGameplayPage).ghostId = ""; + } + + ghostCustomChar.onChange = function(_) { + ghostTypeButton.disabled = !ghostCustomChar.selected; + if (!ghostCustomChar.selected) Screen.instance.removeComponent(attachedMenu); + + if (ghostChar.visible && ghostCustomChar.selected) cast(daPage, CharCreatorGameplayPage).ghostId = charId; } ghostTypeButton.onClick = function(_) { @@ -38,11 +57,9 @@ class GhostSettingsDialog extends DefaultPageDialog ghostAnimDropdown.onChange = function(_) { if (ghostAnimDropdown.selectedIndex == -1) return; - cast(daPage, CharCreatorGameplayPage).ghostCharacter.playAnimation(ghostAnimDropdown.selectedItem.text); + ghostChar.playAnimation(ghostAnimDropdown.selectedItem.text); } } - - function releaseTheGhouls() {} } /** @@ -85,23 +102,28 @@ class GhostCharacterMenu extends Menu charButton.padding = 8; charButton.iconPosition = "top"; - /*if (charId == state.selectedChar.characterId) - { - // Scroll to the character if it is already selected. - ghostSelectScroll.hscrollPos = Math.floor(charIndex / 5) * 80; - charButton.selected = true; + if (charId == parent.charId) + { + // Scroll to the character if it is already selected. + ghostSelectScroll.hscrollPos = Math.floor(charIndex / 5) * 80; + charButton.selected = true; - defaultText = '${charData.name} [${charId}]'; - }*/ + defaultText = '${charData.name} [${charId}]'; + } var LIMIT = 6; charButton.icon = CharacterDataParser.getCharPixelIconAsset(charId); charButton.text = charData.name.length > LIMIT ? '${charData.name.substr(0, LIMIT)}.' : '${charData.name}'; - charButton.onClick = _ -> - { - // kill and replace - }; + charButton.onClick = _ -> { + parent.charId = charId; + + var gameplayPage = cast(page, CharCreatorGameplayPage); + if (gameplayPage.ghostCharacter.visible) gameplayPage.ghostId = charId; + + parent.ghostTypeButton.text = charButton.text; + parent.ghostTypeButton.icon = charButton.icon; + }; charButton.onMouseOver = _ -> { ghostIconName.text = '${charData.name} [${charId}]'; diff --git a/source/funkin/ui/debug/char/components/wizard/AddCharFilesDialog.hx b/source/funkin/ui/debug/char/components/wizard/AddCharFilesDialog.hx index 92e5542679..1ccb665a99 100644 --- a/source/funkin/ui/debug/char/components/wizard/AddCharFilesDialog.hx +++ b/source/funkin/ui/debug/char/components/wizard/AddCharFilesDialog.hx @@ -39,9 +39,7 @@ class AddCharFilesDialog extends DefaultWizardDialog switch (params.renderType) { case "sparrow" | "multisparrow": - if (params.renderType == "multisparrow") recursiveAssetsBox(); - else - addAssetsBox.addComponent(new UploadAssetsBox("Put the path to the Spritesheet Image here.", FileUtil.FILE_EXTENSION_INFO_PNG)); + addAssetsBox.addComponent(new UploadAssetsBox("Put the path to the Spritesheet Image here.", FileUtil.FILE_EXTENSION_INFO_PNG)); case "packer": addAssetsBox.addComponent(new UploadAssetsBox("Put the path to the Spritesheet Image here.", FileUtil.FILE_EXTENSION_INFO_PNG)); @@ -59,12 +57,8 @@ class AddCharFilesDialog extends DefaultWizardDialog if (addAssetsBox.disabled) return true; var uploadBoxes:Array = []; - for (i => box in addAssetsBox.childComponents) + for (box in addAssetsBox.childComponents) { - if (stupidFuckingRenderCheck == "multisparrow" && i == addAssetsBox.childComponents.length - 1) - { - continue; - } if (Std.isOfType(box, UploadAssetsBox)) uploadBoxes.push(cast box); } @@ -83,44 +77,31 @@ class AddCharFilesDialog extends DefaultWizardDialog switch (params.renderType) { case "sparrow" | "multisparrow": - var files = []; - for (uploadBox in uploadBoxes) - { - var imgPath = uploadBox.daField.text; - var xmlPath = uploadBox.daField.text.replace(".png", ".xml"); - - // checking if we even have the correct file types in the correct places - if (Path.extension(imgPath) != "png" || Path.extension(xmlPath) != "xml") return false; + var imgPath = uploadBoxes[0].daField.text; + var xmlPath = uploadBoxes[0].daField.text.replace(".png", ".xml"); - // testing if we could actually use these - var imgBytes = CharCreatorUtil.gimmeTheBytes(imgPath); - var xmlBytes = CharCreatorUtil.gimmeTheBytes(xmlPath); + // checking if we even have the correct file types in the correct places + if (Path.extension(imgPath) != "png" || Path.extension(xmlPath) != "xml") return false; - var tempSprite = new FlxSprite(); - try - { - var bitmap = BitmapData.fromBytes(imgBytes); - tempSprite.frames = FlxAtlasFrames.fromSparrow(bitmap, xmlBytes.toString()); - } - catch (e) - { - tempSprite.destroy(); - return false; - } + // testing if we could actually use these + var imgBytes = CharCreatorUtil.gimmeTheBytes(imgPath); + var xmlBytes = CharCreatorUtil.gimmeTheBytes(xmlPath); - tempSprite.destroy(); // fuck this guy i hate him - files = files.concat([ - { - name: imgPath, - bytes: imgBytes - }, - { - name: xmlPath, - bytes: xmlBytes - } - ]); + var tempSprite = new FlxSprite(); + try + { + var bitmap = BitmapData.fromBytes(imgBytes); + tempSprite.frames = FlxAtlasFrames.fromSparrow(bitmap, xmlBytes.toString()); + } + catch (e) + { + tempSprite.destroy(); + return false; } - params.files = files; + + tempSprite.destroy(); // fuck this guy i hate him + params.files = [ + {name: imgPath, bytes: imgBytes}, {name: xmlPath, bytes: xmlBytes}]; return true; @@ -205,16 +186,6 @@ class AddCharFilesDialog extends DefaultWizardDialog return false; } - - function recursiveAssetsBox():Void - { - var uploadAssetsBox:UploadAssetsBox = new UploadAssetsBox("Put the path to the Spritesheet Image here.", FileUtil.FILE_EXTENSION_INFO_PNG); - uploadAssetsBox.daField.onChange = (_) -> { - uploadAssetsBox.daField.onChange = null; - recursiveAssetsBox(); - }; - addAssetsBox.addComponent(uploadAssetsBox); - } } class UploadAssetsBox extends HBox diff --git a/source/funkin/ui/debug/char/components/wizard/DefaultWizardDialog.hx b/source/funkin/ui/debug/char/components/wizard/DefaultWizardDialog.hx index 318d677414..f4da7c3695 100644 --- a/source/funkin/ui/debug/char/components/wizard/DefaultWizardDialog.hx +++ b/source/funkin/ui/debug/char/components/wizard/DefaultWizardDialog.hx @@ -30,6 +30,7 @@ class DefaultWizardDialog extends Dialog var id:Int = step; if (_.button == DialogButton.CANCEL) { + CharCreatorStartupWizard.wizardProcessRunning = false; if (onQuit != null) onQuit(); } else if (_.button == PREVIOUS_STEP_BUTTON) @@ -43,6 +44,7 @@ class DefaultWizardDialog extends Dialog id++; if (id >= dialogArray.length) { + CharCreatorStartupWizard.wizardProcessRunning = false; if (onComplete != null) onComplete(params); return; } diff --git a/source/funkin/ui/debug/char/import.hx b/source/funkin/ui/debug/char/import.hx index 9edbe6f9a8..1d3ae589a9 100644 --- a/source/funkin/ui/debug/char/import.hx +++ b/source/funkin/ui/debug/char/import.hx @@ -1,6 +1,7 @@ package funkin.ui.debug.char; -import funkin.ui.debug.char.util.*; +import funkin.ui.debug.char.util.CharCreatorUtil; +import funkin.ui.debug.char.util.GhostUtil; #if !macro using funkin.ui.debug.char.handlers.CharCreatorStartupWizard; diff --git a/source/funkin/ui/debug/char/pages/CharCreatorGameplayPage.hx b/source/funkin/ui/debug/char/pages/CharCreatorGameplayPage.hx index 94ae5bfbcf..479815a907 100644 --- a/source/funkin/ui/debug/char/pages/CharCreatorGameplayPage.hx +++ b/source/funkin/ui/debug/char/pages/CharCreatorGameplayPage.hx @@ -9,6 +9,8 @@ import haxe.ui.components.VerticalRule; import funkin.data.stage.StageData; import funkin.play.stage.Bopper; import funkin.data.stage.StageData.StageDataCharacter; +import funkin.play.character.CharacterData; +import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.character.BaseCharacter.CharacterType; import funkin.play.stage.StageProp; import funkin.data.stage.StageRegistry; @@ -33,11 +35,12 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage // onion skin/ghost public var ghostCharacter:CharCreatorCharacter; + public var ghostId(default, set):String = ""; // empty string means current character override public function new(daState:CharCreatorState, wizardParams:WizardGenerateParams) { super(daState); - curStage = "mainStage"; + curStage = Constants.DEFAULT_STAGE; Conductor.instance.onBeatHit.add(stageBeatHit); @@ -45,12 +48,18 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage add(currentCharacter); ghostCharacter = new CharCreatorCharacter(wizardParams); + ghostCharacter.visible = false; add(ghostCharacter); updateCharPerStageData(); dialogMap.set(Animation, new AddAnimDialog(this, currentCharacter)); dialogMap.set(Ghost, new GhostSettingsDialog(this)); + + // defaults for UI + labelAnimName.text = "None"; + labelAnimOffsetX.text = labelAnimOffsetY.text = "0"; + labelCharType.text = "BF"; } override public function onDialogUpdate(dialog:DefaultPageDialog) @@ -58,14 +67,10 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage if (dialog == dialogMap[Animation]) { var animDialog = cast(dialogMap[Animation], AddAnimDialog); - var ghostDialog = cast(dialogMap[Ghost], GhostSettingsDialog); labelAnimName.text = animDialog.charAnimDropdown.selectedItem.text; labelAnimOffsetX.text = "" + currentCharacter.getAnimationData(labelAnimName.text).offsets[0]; labelAnimOffsetY.text = "" + currentCharacter.getAnimationData(labelAnimName.text).offsets[1]; - - GhostUtil.copyFromCharacter(ghostCharacter, currentCharacter); - ghostDialog.ghostAnimDropdown.dataSource = animDialog.charAnimDropdown.dataSource; } } @@ -82,15 +87,14 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage } } - var labelAnimName:Label; - var labelAnimOffsetX:Label; - var labelAnimOffsetY:Label; - var labelCharType:Label; + var labelAnimName:Label = new Label(); + var labelAnimOffsetX:Label = new Label(); + var labelAnimOffsetY:Label = new Label(); + var labelCharType:Label = new Label(); override public function fillUpBottomBar(left:Box, middle:Box, right:Box) { // ==================left================== - labelAnimName = new Label(); labelAnimName.text = "None"; labelAnimName.styleNames = "infoText"; labelAnimName.verticalAlign = "center"; @@ -101,8 +105,6 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage leftRule1.percentHeight = 80; left.addComponent(leftRule1); - labelAnimOffsetX = new Label(); - labelAnimOffsetX.text = "0"; labelAnimOffsetX.styleNames = "infoText"; labelAnimOffsetX.verticalAlign = "center"; labelAnimOffsetX.tooltip = "Left/Right Click to Increase/Decrease the Horizontal Offset."; @@ -112,8 +114,6 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage leftRule2.percentHeight = 80; left.addComponent(leftRule2); - labelAnimOffsetY = new Label(); - labelAnimOffsetY.text = "0"; labelAnimOffsetY.styleNames = "infoText"; labelAnimOffsetY.verticalAlign = "center"; labelAnimOffsetY.tooltip = "Left/Right Click to Increase/Decrease the Vertical Offset."; @@ -124,8 +124,6 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage // ==================right================== var typesArray = [BF, GF, DAD]; - labelCharType = new Label(); - labelCharType.text = "BF"; labelCharType.styleNames = "infoText"; labelCharType.verticalAlign = "center"; labelCharType.tooltip = "Left Click/Right Click to switch to the Next/Previous Character Mode."; @@ -203,13 +201,11 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage var animOffsets = currentCharacter.animations[drop.selectedIndex].offsets; var newOffsets = [animOffsets[0] + changeX, animOffsets[1] + changeY]; - currentCharacter.animations[drop.selectedIndex].offsets = newOffsets; - currentCharacter.setAnimationOffsets(currentCharacter.animations[drop.selectedIndex].name, newOffsets[0], newOffsets[1]); // todo: probs merge there two lol + currentCharacter.setAnimationOffsets(currentCharacter.animations[drop.selectedIndex].name, newOffsets[0], newOffsets[1]); currentCharacter.playAnimation(currentCharacter.animations[drop.selectedIndex].name); // GhostUtil.copyFromCharacter(ghostCharacter, currentCharacter); very costly for memory! we're just gonna update the offsets - ghostCharacter.animations[drop.selectedIndex].offsets = newOffsets; - ghostCharacter.setAnimationOffsets(ghostCharacter.animations[drop.selectedIndex].name, newOffsets[0], newOffsets[1]); // todo: probs merge there two lol + if (ghostId == "") ghostCharacter.setAnimationOffsets(ghostCharacter.animations[drop.selectedIndex].name, newOffsets[0], newOffsets[1]); // might as well update the text labelAnimOffsetX.text = "" + newOffsets[0]; @@ -233,6 +229,40 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage item.addComponent(checkGhost); } + public function refreshGhoulAnims() + { + var ghostDialog = cast(dialogMap[Ghost], GhostSettingsDialog); + ghostDialog.ghostAnimDropdown.dataSource.clear(); + for (anim in ghostCharacter.animations) + ghostDialog.ghostAnimDropdown.dataSource.add({text: anim.name}); + } + + function set_ghostId(value:String) + { + if (ghostId == value) return ghostId; + this.ghostId = value; + + var animDialog = cast(dialogMap[Animation], AddAnimDialog); + var ghostDialog = cast(dialogMap[Ghost], GhostSettingsDialog); + + if (ghostId == "") + { + GhostUtil.copyFromCharacter(ghostCharacter, currentCharacter); + } + else + { + var data:CharacterData = CharacterDataParser.fetchCharacterData(ghostId); + if (data == null) return ghostId; + + GhostUtil.copyFromCharacterData(ghostCharacter, data); + } + + refreshGhoulAnims(); + updateCharPerStageData(currentCharacter.characterType); + + return ghostId; + } + override public function performCleanup() { Conductor.instance.onBeatHit.remove(stageBeatHit); @@ -245,17 +275,17 @@ class CharCreatorGameplayPage extends CharCreatorDefaultPage if (charStageDatas[type] == null) return; currentCharacter.zIndex = charStageDatas[type].zIndex; - currentCharacter.x = charStageDatas[type].position[0] - currentCharacter.characterOrigin.x; - currentCharacter.y = charStageDatas[type].position[1] - currentCharacter.characterOrigin.y; + currentCharacter.x = charStageDatas[type].position[0] - currentCharacter.characterOrigin.x + currentCharacter.globalOffsets[0]; + currentCharacter.y = charStageDatas[type].position[1] - currentCharacter.characterOrigin.y + currentCharacter.globalOffsets[1]; currentCharacter.totalScale = currentCharacter.characterScale * charStageDatas[type].scale; currentCharacter.flipX = (type == BF ? !currentCharacter.characterFlipX : currentCharacter.characterFlipX); ghostCharacter.characterType = currentCharacter.characterType = type; ghostCharacter.alpha = GHOST_SKIN_ALPHA; - ghostCharacter.zIndex = currentCharacter.zIndex - 1; // should onion skin be behind or in front? - ghostCharacter.x = charStageDatas[type].position[0] - ghostCharacter.characterOrigin.x; - ghostCharacter.y = charStageDatas[type].position[1] - ghostCharacter.characterOrigin.y; + ghostCharacter.zIndex = currentCharacter.zIndex + 1; // should onion skin be behind or in front? + ghostCharacter.x = charStageDatas[type].position[0] - ghostCharacter.characterOrigin.x + ghostCharacter.globalOffsets[0]; + ghostCharacter.y = charStageDatas[type].position[1] - ghostCharacter.characterOrigin.y + ghostCharacter.globalOffsets[1]; ghostCharacter.totalScale = ghostCharacter.characterScale * charStageDatas[type].scale; ghostCharacter.flipX = (type == BF ? !ghostCharacter.characterFlipX : ghostCharacter.characterFlipX); diff --git a/source/funkin/ui/debug/char/util/GhostUtil.hx b/source/funkin/ui/debug/char/util/GhostUtil.hx index 63c800d5ff..d3f09f462b 100644 --- a/source/funkin/ui/debug/char/util/GhostUtil.hx +++ b/source/funkin/ui/debug/char/util/GhostUtil.hx @@ -1,8 +1,10 @@ package funkin.ui.debug.char.util; +import funkin.play.character.CharacterData; import funkin.ui.debug.char.animate.CharSelectAtlasSprite; import funkin.ui.debug.char.pages.CharCreatorGameplayPage; import flixel.graphics.frames.FlxAtlasFrames; +import openfl.Assets; import openfl.display.BitmapData; // utilities for the onion skin/ghost character @@ -11,16 +13,26 @@ class GhostUtil public static function copyFromCharacter(ghost:CharCreatorCharacter, player:CharCreatorCharacter) { ghost.generatedParams = player.generatedParams; + ghost.animations = []; ghost.atlasCharacter = null; + ghost.loadGraphic(null); // should remove all the frames and animations i think switch (player.renderType) { case "sparrow" | "multisparrow": if (ghost.generatedParams.files.length != 2) return; // img and data - var img = BitmapData.fromBytes(ghost.generatedParams.files[0].bytes); - var data = ghost.generatedParams.files[1].bytes.toString(); - ghost.frames = FlxAtlasFrames.fromSparrow(img, data); + var combinedFrames = null; + for (i in 0...Math.floor(ghost.generatedParams.files.length / 2)) + { + var img = BitmapData.fromBytes(ghost.generatedParams.files[i * 2].bytes); + var data = ghost.generatedParams.files[i * 2 + 1].bytes.toString(); + var sparrow = FlxAtlasFrames.fromSparrow(img, data); + if (combinedFrames == null) combinedFrames = sparrow; + else + combinedFrames.addAtlas(sparrow); + } + ghost.frames = combinedFrames; case "packer": if (ghost.generatedParams.files.length != 2) return; // img and data @@ -53,7 +65,51 @@ class GhostUtil for (anim in player.animations) { ghost.addAnimation(anim.name, anim.prefix, anim.offsets, anim.frameIndices, anim.assetPath, anim.frameRate, anim.looped, anim.flipX, anim.flipY); - ghost.setAnimationOffsets(anim.name, anim.offsets[0], anim.offsets[1]); + } + } + + public static function copyFromCharacterData(ghost:CharCreatorCharacter, data:CharacterData) + { + // ghost.generatedParams = player.generatedParams; + ghost.animations = []; + ghost.atlasCharacter = null; + ghost.loadGraphic(null); // should remove all the frames and animations i think + + switch (data.renderType) + { + case "sparrow": + ghost.frames = Paths.getSparrowAtlas(data.assetPath); + + case "packer": + ghost.frames = Paths.getPackerAtlas(data.assetPath); + + case "multisparrow": // lemz if you're reading this pls don't forget to update this once you're finished reworking multisparrow chars, thanks! + var allAssetPaths:Array = []; + + for (anim in data.animations) + { + if (anim.assetPath != null && !allAssetPaths.contains(anim.assetPath)) allAssetPaths.push(anim.assetPath); + } + + var combinedFrames = Paths.getSparrowAtlas(data.assetPath); + for (path in allAssetPaths) + combinedFrames.addAtlas(Paths.getSparrowAtlas(path)); + + ghost.frames = combinedFrames; + + case "animateatlas": // TODO, gonna think of smth + + default: // nuthin + } + + ghost.globalOffsets = data.offsets ?? [0, 0]; + ghost.characterFlipX = data.flipX ?? false; + ghost.characterScale = data.scale ?? 1; + + for (anim in data.animations) + { + ghost.addAnimation(anim.name, anim.prefix, anim.offsets, anim.frameIndices ?? [], anim.assetPath ?? "", anim.frameRate ?? 24, anim.looped ?? false, + anim.flipX ?? false, anim.flipY ?? false); } } }