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);