diff --git a/assets/editors/layouts/stage/spriteEditScreen.xml b/assets/editors/layouts/stage/spriteEditScreen.xml index d84b8500..a0684432 100644 --- a/assets/editors/layouts/stage/spriteEditScreen.xml +++ b/assets/editors/layouts/stage/spriteEditScreen.xml @@ -47,6 +47,8 @@ + + @@ -69,7 +71,10 @@ function onSave() { sprite.name = nameTextBox.label.text; - sprite.extra.set(exID("imageFile"), spriteTextBox.label.text); + setEx("imageFile", spriteTextBox.label.text); + + setEx("highMemory", highMemoryRadio.checked); + setEx("lowMemory", lowMemoryRadio.checked); sprite.x = xStepper.value; sprite.y = yStepper.value; diff --git a/assets/images/editors/ui/radiobutton.png b/assets/images/editors/ui/radiobutton.png new file mode 100644 index 00000000..a6f7dbce Binary files /dev/null and b/assets/images/editors/ui/radiobutton.png differ diff --git a/source/funkin/editors/stage/StageEditor.hx b/source/funkin/editors/stage/StageEditor.hx index 51f8c3bb..5a46371f 100644 --- a/source/funkin/editors/stage/StageEditor.hx +++ b/source/funkin/editors/stage/StageEditor.hx @@ -187,6 +187,10 @@ class StageEditor extends UIState { sprite.extra.set(exID("node"), node); sprite.extra.set(exID("type"), node.name); sprite.extra.set(exID("imageFile"), '${node.getAtt("sprite").getDefault(sprite.name)}'); + var parent = new Access(node.x.parent); + sprite.extra.set(exID("parentNode"), parent); + sprite.extra.set(exID("highMemory"), parent.name == "highMemory"); + sprite.extra.set(exID("lowMemory"), parent.name == "lowMemory"); //sprite.active = false; } if(sprite is StageCharPos) { diff --git a/source/funkin/editors/stage/StageSpriteEditScreen.hx b/source/funkin/editors/stage/StageSpriteEditScreen.hx index b220c6df..c221b9fa 100644 --- a/source/funkin/editors/stage/StageSpriteEditScreen.hx +++ b/source/funkin/editors/stage/StageSpriteEditScreen.hx @@ -20,7 +20,10 @@ class StageSpriteEditScreen extends UISoftcodedWindow { "exID" => StageEditor.exID, "getEx" => function(name:String):Dynamic { return sprite.extra.get(StageEditor.exID(name)); - } + }, + "setEx" => function(name:String, value:Dynamic) { + sprite.extra.set(StageEditor.exID(name), value); + }, ]); } diff --git a/source/funkin/editors/ui/UICheckbox.hx b/source/funkin/editors/ui/UICheckbox.hx index d3c777b9..426857a5 100644 --- a/source/funkin/editors/ui/UICheckbox.hx +++ b/source/funkin/editors/ui/UICheckbox.hx @@ -10,14 +10,14 @@ class UICheckbox extends UISprite { public function new(x:Float, y:Float, text:String, checked:Bool = false, w:Int = 0) { super(x, y); loadGraphic(Paths.image('editors/ui/checkbox'), true, 20, 20); - for(frame=>name in ["normal", "hover", "pressed", "checkmark"]) + for(frame=>name in ["normal", "hover", "pressed", "selected"]) animation.add(name, [frame], 0, false); this.checked = checked; field = new UIText(x, y, w, text); check = new FlxSprite().loadGraphicFromSprite(this); - check.animation.play("checkmark"); + check.animation.play("selected"); members.push(check); members.push(field); diff --git a/source/funkin/editors/ui/UIRadioButton.hx b/source/funkin/editors/ui/UIRadioButton.hx new file mode 100644 index 00000000..ebff277a --- /dev/null +++ b/source/funkin/editors/ui/UIRadioButton.hx @@ -0,0 +1,105 @@ +package funkin.editors.ui; + +import flixel.util.typeLimit.OneOfTwo; + +class UIRadioButton extends UISprite { + public var checked:Bool = false; + public var onChecked:Bool->Void = null; + + public var field:UIText; + public var check:FlxSprite; + + public var parent:OneOfTwo = null; + public var forID:String = null; + + public function new(x:Float, y:Float, text:String, checked:Bool = false, forID:String = null, w:Int = 0) { + super(x, y); + this.forID = forID; + loadGraphic(Paths.image('editors/ui/radiobutton'), true, 20, 20); + for(frame=>name in ["normal", "hover", "pressed", "selected"]) + animation.add(name, [frame], 0, false); + + this.checked = checked; + this.targetScale = checked ? 1 : 0; + + field = new UIText(x, y, w, text); + check = new FlxSprite().loadGraphicFromSprite(this); + check.animation.play("selected"); + check.scale.set(targetScale, targetScale); + + members.push(check); + members.push(field); + + cursor = CLICK; + + autoAlpha = false; + } + + public var targetScale:Float = 1; + + public override function update(elapsed:Float) { + // ANIMATION HANDLING + animation.play(hovered ? (pressed ? "pressed" : "hover") : "normal"); + + // CHECKMARK HANDLING + if(autoAlpha) + check.alpha = checked ? 1 : 0; + check.scale.x = CoolUtil.fpsLerp(check.scale.x, targetScale, 0.25); + check.scale.y = CoolUtil.fpsLerp(check.scale.y, targetScale, 0.25); + + // POSITION HANDLING + updatePositions(); + + super.update(elapsed); + } + + public inline function updatePositions() { + check.follow(this); + field.follow(this, 25, 0); + } + + public override function draw() { + updatePositions(); + super.draw(); + } + + public override function onHovered() { + super.onHovered(); + if (FlxG.mouse.justReleased) { + // clicked + checked = !checked; + check.scale.set(1.25, 1.25); + targetScale = checked ? 1 : 0; + + if (Options.editorSFX) + CoolUtil.playMenuSFX(checked ? CHECKED : UNCHECKED, 0.5); + + if(parent != null) { + var members = (parent is UIWindow) ? (cast(parent, UIWindow)).members : (cast(parent, UISubstateWindow)).members; + var radios:Array = cast members.filter((o) -> o is UIRadioButton && o != this); + //trace(radios); + for(radio in radios) { + if(radio.forID != null && radio.forID == forID) { + radio.checked = false; + radio.targetScale = 0; + } + } + } + + if (onChecked != null) + onChecked(checked); + } + } + + public override function updateButton() { + __rect.x = x; + __rect.y = y; + __rect.width = field.width + 30; + __rect.height = field.height > height ? field.height : height; + UIState.state.updateRectButtonHandler(this, __rect, onHovered); + } + + public override function toString() { + return "RadioButton(" + field.text + ", " + checked + ", " + forID + ")"; + } +} \ No newline at end of file diff --git a/source/funkin/editors/ui/UISoftcodedWindow.hx b/source/funkin/editors/ui/UISoftcodedWindow.hx index 49947b8d..ff751fec 100644 --- a/source/funkin/editors/ui/UISoftcodedWindow.hx +++ b/source/funkin/editors/ui/UISoftcodedWindow.hx @@ -45,6 +45,7 @@ class UISoftcodedWindow extends UISubstateWindow { } function execString(input:String):String { + if(input == null) return null; if(input.indexOf("${") == -1) return input; var text = ""; while(input.length > 0) { @@ -109,6 +110,10 @@ class UISoftcodedWindow extends UISubstateWindow { } set("self", this); set("hasSaveButtons", true); + set("getRadioButtons", function(forID:String) { + var radios:Array = cast members.filter((o) -> o is UIRadioButton); + return cast radios.filter((o) -> o.forID == forID); + }); for(k=>v in customVariables) { set(k, v); } @@ -178,6 +183,12 @@ class UISoftcodedWindow extends UISubstateWindow { add(checkbox); addLabelOn(checkbox, label); checkbox; + case "radio": + var radio = new UIRadioButton(x, y, text, execAtt(el, "value", false), execString(el.getAtt("for"))); + radio.parent = this; + add(radio); + addLabelOn(radio, label); + radio; case "slider": var slider = new UISlider(x, y, width, execAtt(el, "value", 0), execAtt(el, "segments", []), execAtt(el, "centered", false)); add(slider);