diff --git a/.gitignore b/.gitignore index 77035890a7..a78fed33c7 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ addons/* addons/* !addons/readme.txt dev-libs/ +.vs/ \ No newline at end of file diff --git a/assets/languages/en/Editors.xml b/assets/languages/en/Editors.xml index c36b63b5e1..fe60cf0f53 100644 --- a/assets/languages/en/Editors.xml +++ b/assets/languages/en/Editors.xml @@ -357,6 +357,7 @@ Icon Icon Color Sing Duration + Default FPS Use Sing Duration? Custom Values (Advanced) diff --git a/source/funkin/editors/character/CharacterAnimsWindow.hx b/source/funkin/editors/character/CharacterAnimsWindow.hx index bcdd4e5184..b31a071f34 100644 --- a/source/funkin/editors/character/CharacterAnimsWindow.hx +++ b/source/funkin/editors/character/CharacterAnimsWindow.hx @@ -150,7 +150,7 @@ class CharacterAnimsWindow extends UIButtonList { var animData:AnimData = { name: animName, anim: __autoCompleteAnims[0], - fps: 24, loop: false, + fps: character.defaultAimFPS, loop: false, x: 0, y: 0, indices: [], animType: NONE, diff --git a/source/funkin/editors/character/CharacterInfoScreen.hx b/source/funkin/editors/character/CharacterInfoScreen.hx index f085d2c338..383bece7df 100644 --- a/source/funkin/editors/character/CharacterInfoScreen.hx +++ b/source/funkin/editors/character/CharacterInfoScreen.hx @@ -8,6 +8,8 @@ import openfl.geom.Point; import openfl.geom.Rectangle; import openfl.display.BitmapData; import funkin.game.Character; +import funkin.backend.utils.XMLUtil.AnimData; +import funkin.editors.character.CharacterEditor; using funkin.backend.utils.BitmapUtil; @@ -15,6 +17,7 @@ typedef CharacterExtraInfo = { var icon:String; var iconColor:Null; var holdTime:Float; + var defaultAimFPS:Float; var customProperties:Map; } @@ -26,12 +29,15 @@ class CharacterInfoScreen extends UISubstateWindow { public var useDurationCheckbox:UICheckbox; public var durationStepper:UINumericStepper; + public var defaultAimFPS:UINumericStepper; public var customPropertiesButtonList:UIButtonList; public var saveButton:UIButton; public var closeButton:UIButton; + var oldDefFPS:Float; + public var onSave:(info:CharacterExtraInfo) -> Void = null; public function new(character:Character, onSave:(info:CharacterExtraInfo) -> Void) { @@ -77,6 +83,11 @@ class CharacterInfoScreen extends UISubstateWindow { durationStepper.selectable = useDurationCheckbox.checked; + defaultAimFPS = new UINumericStepper(iconColorPicker.x, durationStepper.y + durationStepper.height + 40, character.defaultAimFPS, 0.001, 2, 0, 9999999, 74); + add(defaultAimFPS); + addLabelOn(defaultAimFPS, translate("defaultFPS")); + oldDefFPS = character.defaultAimFPS; + customPropertiesButtonList = new UIButtonList(iconColorWheel.x+iconColorWheel.bWidth+22, iconColorWheel.y, 290, 200, '', FlxPoint.get(280, 35), null, 5); customPropertiesButtonList.frames = Paths.getFrames('editors/ui/inputbox'); customPropertiesButtonList.cameraSpacing = 0; @@ -107,10 +118,25 @@ class CharacterInfoScreen extends UISubstateWindow { public function saveCharacterInfo() { UIUtil.confirmUISelections(this); + if (defaultAimFPS.value != oldDefFPS){ + var daIDForButton:Int = 0; + for (anim in character.getAnimOrder()){ + var animName = character.animDatas.get(anim); + if (animName.fps == oldDefFPS){ + var poop:CharacterAnimButton = CharacterEditor.instance.characterAnimsWindow.buttons.members[daIDForButton]; + trace(poop); + poop.changeFPS(defaultAimFPS.value); + } + daIDForButton++; + } + } + + if (onSave != null) onSave({ icon: iconColorPicker.iconTextBox.label.text, iconColor: iconColorWheel.curColor, holdTime: useDurationCheckbox.checked ? durationStepper.value : -1, + defaultAimFPS: defaultAimFPS.value, customProperties: [ for (val in customPropertiesButtonList.buttons.members) val.propertyText.label.text => val.valueText.label.text diff --git a/source/funkin/editors/character/CharacterPropertiesWindow.hx b/source/funkin/editors/character/CharacterPropertiesWindow.hx index b877743265..0920f808d4 100644 --- a/source/funkin/editors/character/CharacterPropertiesWindow.hx +++ b/source/funkin/editors/character/CharacterPropertiesWindow.hx @@ -159,12 +159,14 @@ class CharacterPropertiesWindow extends UISliceSprite { icon: character.icon, iconColor: character.iconColor, holdTime: character.holdTime, + defaultAimFPS: character.defaultAimFPS, customProperties: character.extra.copy() }; character.icon = info.icon; character.iconColor = info.iconColor; character.holdTime = info.holdTime; + character.defaultAimFPS = info.defaultAimFPS; character.extra = info.customProperties.copy(); if (addToUndo) CharacterEditor.undos.addToUndo(CCharEditInfo(oldInfo, info)); diff --git a/source/funkin/game/Character.hx b/source/funkin/game/Character.hx index 7ecbe0b777..5c08a7001d 100644 --- a/source/funkin/game/Character.hx +++ b/source/funkin/game/Character.hx @@ -46,6 +46,8 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset public var icon:String = null; public var iconColor:Null = null; public var gameOverCharacter:String = Character.FALLBACK_DEAD_CHARACTER; + public var defaultAimFPS:Float = 24; + public var cameraOffset:FlxPoint = FlxPoint.get(0, 0); public var globalOffset:FlxPoint = FlxPoint.get(0, 0); @@ -373,6 +375,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset if (xml.x.exists("x")) globalOffset.x = Std.parseFloat(xml.x.get("x")); if (xml.x.exists("y")) globalOffset.y = Std.parseFloat(xml.x.get("y")); if (xml.x.exists("gameOverChar")) gameOverCharacter = xml.x.get("gameOverChar"); + if (xml.x.exists("defFps")) defaultAimFPS = Std.parseFloat(xml.x.get("defFps")); if (xml.x.exists("camx")) cameraOffset.x = Std.parseFloat(xml.x.get("camx")); if (xml.x.exists("camy")) cameraOffset.y = Std.parseFloat(xml.x.get("camy")); if (xml.x.exists("holdTime")) holdTime = Std.parseFloat(xml.x.get("holdTime")).getDefaultFloat(4); @@ -408,7 +411,13 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset loadSprite(Paths.image('characters/$sprite')); for(node in xml.elements) { switch(node.name) { - case "anim": + case "anim": + if (defaultAimFPS != 24){ + if (!node.x.exists("fps")) { + node.x.set('fps', Std.string(defaultAimFPS)); + } + } + XMLUtil.addXMLAnimation(this, node); case "use-extension" | "extension" | "ext": if (XMLImportedScriptInfo.shouldLoadBefore(node)) continue; @@ -439,7 +448,8 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset public static var characterProperties:Array = [ "x", "y", "sprite", "scale", "antialiasing", "flipX", "camx", "camy", "isPlayer", "icon", - "color", "gameOverChar", "holdTime", "applyStageMatrix" + "color", "gameOverChar", "holdTime", "applyStageMatrix", + "defFps" ]; public static var characterAnimProperties:Array = [ "name", "anim", "label", "x", "y", "fps", "loop", "indices" @@ -463,6 +473,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset if (gameOverCharacter != Character.FALLBACK_DEAD_CHARACTER) xml.set("gameOverChar", gameOverCharacter); if (iconColor != null) xml.set("color", iconColor.toWebString()); + if (defaultAimFPS != 24) xml.set("defFps", Std.string(defaultAimFPS)); if (sprite != curCharacter) xml.set("sprite", sprite); if (scale.x != 1) xml.set("scale", Std.string(FlxMath.roundDecimal(scale.x, 4))); @@ -485,7 +496,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset animXml.set("name", anim.name); animXml.set("anim", anim.anim); if (anim.loop) animXml.set("loop", Std.string(anim.loop)); - if (FlxMath.roundDecimal(anim.fps, 2) != 24) animXml.set("fps", Std.string(FlxMath.roundDecimal(anim.fps, 2))); + if (FlxMath.roundDecimal(anim.fps, 2) != defaultAimFPS) animXml.set("fps", Std.string(FlxMath.roundDecimal(anim.fps, 2))); var offset:FlxPoint = getAnimOffset(anim.name); if (FlxMath.roundDecimal(offset.x, 2) != 0) animXml.set("x", Std.string(FlxMath.roundDecimal(offset.x, 2)));