diff --git a/assets/data/editors/layouts/stage/spriteEditScreen.xml b/assets/data/editors/layouts/stage/spriteEditScreen.xml
index 9c49f410..9c0c20fe 100644
--- a/assets/data/editors/layouts/stage/spriteEditScreen.xml
+++ b/assets/data/editors/layouts/stage/spriteEditScreen.xml
@@ -119,6 +119,13 @@
button.xml.set(name + "y", y.value);
}
}
+ function save(name:String, value:Dynamic) {
+ button.xml.remove(name);
+ button.xml.set(name, value);
+ }
+
+ // TODO: remove old attributes to prevent possible errors
+ // button.xml.remove();
button.xml.set("name", nameTextBox.label.text);
button.xml.set("sprite", spriteTextBox.label.text);
diff --git a/assets/data/editors/layouts/stage/stageInfoScreen.xml b/assets/data/editors/layouts/stage/stageInfoScreen.xml
new file mode 100644
index 00000000..d5e2bfaf
--- /dev/null
+++ b/assets/data/editors/layouts/stage/stageInfoScreen.xml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+ function col(c:Int) {
+ return MARGIN + (170 + XOFFSET) * c;
+ }
+
+ for(prop => val in stage.extra)
+ if(!StringTools.startsWith(prop, "stageEditor."))
+ storedProps.push(prop);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ import funkin.editors.extra.PropertyButton;
+
+ var buttonList = buttonlist; // important for now, since it gets reset after the code is run
+
+ var width = buttonList.buttonSize.x;
+ var height = buttonList.buttonSize.y;
+
+ buttonList.addButton.callback = function() {
+ buttonList.add(new PropertyButton("newProperty", "valueHere", buttonList, width, height, 150, 220, 25));
+ }
+
+ //var defaultAttribs = Stage.DEFAULT_ATTRIBUTES;
+ //for (i in stage.stageXML.attributes()) {
+ // trace(i, defaultAttribs);
+ // if (!defaultAttribs.contains(i))
+ // buttonList.add(new PropertyButton(i, stage.stageXML.get(i), buttonList, width, height, 150, 220, 25));
+ //}
+ for(key => val in stage.extra)
+ buttonList.add(new PropertyButton(key, val, buttonList, width, height, 150, 220, 25));
+
+
+
+
+
+ function onSave() {
+ stage.startCam.x = camxStepper.value;
+ stage.startCam.y = camyStepper.value;
+ stage.defaultZoom = zoomStepper.value;
+ stage.stageName = nameTextBox.label.text;
+ stage.spritesParentFolder = spritePathTextBox.label.text;
+
+ for(prop in storedProps)
+ stage.extra.remove(prop);
+
+ for(prop in attributesList.buttons.members)
+ stage.extra.set(prop.propertyText.label.text, prop.valueText.label.text);
+ }
+
+
\ No newline at end of file
diff --git a/assets/data/editors/layouts/stage/unknownEditScreen.xml b/assets/data/editors/layouts/stage/unknownEditScreen.xml
index b2b54542..ec6f3d71 100644
--- a/assets/data/editors/layouts/stage/unknownEditScreen.xml
+++ b/assets/data/editors/layouts/stage/unknownEditScreen.xml
@@ -56,6 +56,9 @@
button.highMemory = highMemoryRadio.checked;
button.lowMemory = lowMemoryRadio.checked;
+ for (i in xml.attributes())
+ xml.remove(i);
+
for (val in attributesList.buttons.members)
xml.set(val.propertyText.label.text, val.valueText.label.text);
}
diff --git a/assets/data/stages/test.xml b/assets/data/stages/test.xml
index be041748..697711bb 100644
--- a/assets/data/stages/test.xml
+++ b/assets/data/stages/test.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/source/funkin/backend/utils/WindowUtils.hx b/source/funkin/backend/utils/WindowUtils.hx
index 571f781a..d6210d9a 100644
--- a/source/funkin/backend/utils/WindowUtils.hx
+++ b/source/funkin/backend/utils/WindowUtils.hx
@@ -28,7 +28,7 @@ class WindowUtils {
static var __triedClosing:Bool = false;
public static inline function resetClosing() __triedClosing = false;
- public static inline function init() {
+ public static function init() {
resetTitle();
resetClosing();
diff --git a/source/funkin/editors/stage/StageEditor.hx b/source/funkin/editors/stage/StageEditor.hx
index 2e73cc54..411a1de2 100644
--- a/source/funkin/editors/stage/StageEditor.hx
+++ b/source/funkin/editors/stage/StageEditor.hx
@@ -96,10 +96,10 @@ class StageEditor extends UIState {
}
]
},
- /*{
+ {
label: "Edit",
childs: [
- {
+ /*{
label: "Undo",
keybind: [CONTROL, Z],
onSelect: _edit_undo,
@@ -109,9 +109,25 @@ class StageEditor extends UIState {
keybind: [CONTROL, SHIFT, Z],
onSelect: _edit_redo,
},
- null,
+ null,*/
+ {
+ label: "Edit Stage Info",
+ onSelect: (_) -> {
+ openSubState(new UISoftcodedWindow(
+ "layouts/stage/stageInfoScreen",
+ [
+ "winTitle" => "Editing Stage Info",
+ "hasSaveButton" => true,
+ "hasCloseButton" => true,
+ "stage" => stage,
+ "Stage" => Stage,
+ "exID" => exID
+ ]
+ ));
+ },
+ }
]
- },*/
+ },
{
label: "Select",
childs: [
@@ -586,6 +602,10 @@ class StageEditor extends UIState {
saveToXml(xml, "startCamPosX", stage.startCam.x, 0);
saveToXml(xml, "startCamPosY", stage.startCam.y, 0);
+ for(prop in stage.extra.keys())
+ if(!Stage.DEFAULT_ATTRIBUTES.contains(prop) && !prop.startsWith("stageEditor."))
+ saveToXml(xml, prop, stage.extra.get(prop));
+
var group:Xml = null;
var curGroup:String = null;
@@ -742,11 +762,11 @@ class StageEditor extends UIState {
}
}*/
- public function editInfoWithUI() {
+ /*public function editInfoWithUI() {
FlxG.state.openSubState(new StageInfoScreen(stage, (_) -> {
if (_ != null) editInfo(_);
}));
- }
+ }*/
public function editInfo(newInfo:Xml, addtoUndo:Bool = true) {
/*var oldInfo = stage.buildXML();
diff --git a/source/funkin/editors/stage/StageInfoScreen.hx b/source/funkin/editors/stage/StageInfoScreen.hx
deleted file mode 100644
index 10fe046b..00000000
--- a/source/funkin/editors/stage/StageInfoScreen.hx
+++ /dev/null
@@ -1,169 +0,0 @@
-package funkin.editors.stage;
-
-import flixel.math.FlxPoint;
-import funkin.editors.extra.PropertyButton;
-import funkin.game.Stage;
-import haxe.xml.Access;
-
-class StageInfoScreen extends UISubstateWindow {
- public var stage:Stage;
-
- public var saveButton:UIButton;
- public var closeButton:UIButton;
-
- public var onSave:(xml:Xml) -> Void = null;
-
- public function new(stage:Stage, ?onSave:(xml:Xml) -> Void) {
- this.stage = stage;
- this.onSave = onSave;
- super();
- }
-
- public override function create() {
- winTitle = "Editing Stage";
- winWidth = 1014;
- winHeight = 600;
-
- super.create();
-
- function addLabelOn(ui:UISprite, text:String)
- add(new UIText(ui.x, ui.y - 24, 0, text));
-
- /*var title:UIText;
- add(title = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Sprite Data", 28));
-
- spriteTextBox = new UITextBox(title.x, title.y + title.height + 38, character.sprite, 200);
- add(spriteTextBox);
- addLabelOn(spriteTextBox, "Sprite");
-
- iconTextBox = new UITextBox(spriteTextBox.x + 200 + 26, spriteTextBox.y, character.getIcon(), 150);
- iconTextBox.onChange = (newIcon:String) -> {updateIcon(newIcon);}
- add(iconTextBox);
- addLabelOn(iconTextBox, "Icon");
-
- updateIcon(character.getIcon());
-
- gameOverCharTextBox = new UITextBox(iconTextBox.x + 150 + (75 + 12), iconTextBox.y, character.gameOverCharacter, 200);
- add(gameOverCharTextBox);
- addLabelOn(gameOverCharTextBox, "Game Over Character");
-
- antialiasingCheckbox = new UICheckbox(spriteTextBox.x, spriteTextBox.y + 10 + 32 + 28, "Antialiasing", character.antialiasing);
- add(antialiasingCheckbox);
- addLabelOn(antialiasingCheckbox, "Antialiased");
-
- flipXCheckbox = new UICheckbox(antialiasingCheckbox.x + 172, spriteTextBox.y + 10 + 32 + 28, "FlipX", character.flipX);
- add(flipXCheckbox);
- addLabelOn(flipXCheckbox, "Flipped");
-
- iconColorWheel = new UIColorwheel(gameOverCharTextBox.x + 200 + 20, gameOverCharTextBox.y, character.iconColor);
- add(iconColorWheel);
- addLabelOn(iconColorWheel, "Icon Color");
-
- add(title = new UIText(spriteTextBox.x, spriteTextBox.y + 10 + 46 + 84, 0, "Character Data", 28));
-
- positionXStepper = new UINumericStepper(title.x, title.y + title.height + 36, character.globalOffset.x, 0.001, 2, null, null, 84);
- add(positionXStepper);
- addLabelOn(positionXStepper, "Position (X,Y)");
-
- add(new UIText(positionXStepper.x + 84 - 32 + 0, positionXStepper.y + 9, 0, ",", 22));
-
- positionYStepper = new UINumericStepper(positionXStepper.x + 84 - 32 + 26, positionXStepper.y, character.globalOffset.y, 0.001, 2, null, null, 84);
- add(positionYStepper);
-
- cameraXStepper = new UINumericStepper(positionYStepper.x + 36 + 84 - 32, positionYStepper.y, character.cameraOffset.x, 0.001, 2, null, null, 84);
- add(cameraXStepper);
- addLabelOn(cameraXStepper, "Camera Position (X,Y)");
-
- add(new UIText(cameraXStepper.x + 84 - 32 + 0, cameraXStepper.y + 9, 0, ",", 22));
-
- cameraYStepper = new UINumericStepper(cameraXStepper.x + 84 - 32 + 26, cameraXStepper.y, character.cameraOffset.y, 0.001, 2, null, null, 84);
- add(cameraYStepper);
-
- scaleStepper = new UINumericStepper(cameraYStepper.x + 84 - 32 + 90, cameraYStepper.y, character.scale.x, 0.001, 2, null, null, 74);
- add(scaleStepper);
- addLabelOn(scaleStepper, "Scale");
-
- singTimeStepper = new UINumericStepper(scaleStepper.x + 74 - 32 + 36, scaleStepper.y, character.holdTime, 0.001, 2, null, null, 74);
- add(singTimeStepper);
- addLabelOn(singTimeStepper, "Sing Duration (Steps)");
-
- customPropertiesButtonList = new UIButtonList(singTimeStepper.x + singTimeStepper.width + 200, singTimeStepper.y, 290, 200, '', FlxPoint.get(280, 35), null, 5);
- customPropertiesButtonList.frames = Paths.getFrames('editors/ui/inputbox');
- customPropertiesButtonList.cameraSpacing = 0;
- customPropertiesButtonList.addButton.callback = function() {
- customPropertiesButtonList.add(new PropertyButton("newProperty", "valueHere", customPropertiesButtonList));
- }
- for (prop=>val in character.extra)
- customPropertiesButtonList.add(new PropertyButton(prop, val, customPropertiesButtonList));
- add(customPropertiesButtonList);
- addLabelOn(customPropertiesButtonList, "Custom Values (Advanced)");
-
- isPlayerCheckbox = new UICheckbox(positionXStepper.x, positionXStepper.y + 10 + 32 + 28, "isPlayer", character.playerOffsets);
- add(isPlayerCheckbox);
- addLabelOn(isPlayerCheckbox, "Is Player");
-
- isGFCheckbox = new UICheckbox(isPlayerCheckbox.x + 128, positionXStepper.y + 10 + 32 + 28, "isGF", character.isGF);
- add(isGFCheckbox);
- addLabelOn(isGFCheckbox, "Is GF");
-
- for (checkbox in [isPlayerCheckbox, isGFCheckbox, antialiasingCheckbox, flipXCheckbox])
- {checkbox.y += 4; checkbox.x += 6;}*/
-
- saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, windowSpr.y + windowSpr.bHeight- 20, "Save & Close", function() {
- //saveCharacterInfo();
- close();
- }, 125);
- saveButton.x -= saveButton.bWidth;
- saveButton.y -= saveButton.bHeight;
-
- closeButton = new UIButton(saveButton.x - 20, saveButton.y, "Close", function() {
- if (onSave != null) onSave(null);
- close();
- }, 125);
- closeButton.x -= closeButton.bWidth;
- closeButton.color = 0xFFFF0000;
- add(closeButton);
- add(saveButton);
- }
-
- /*function saveCharacterInfo() {
- for (stepper in [positionXStepper, positionYStepper, cameraXStepper, cameraYStepper, singTimeStepper, scaleStepper])
- @:privateAccess stepper.__onChange(stepper.label.text);
-
- var xml = Xml.createElement("character");
- xml.set("isPlayer", isPlayerCheckbox.checked ? "true" : "false");
- xml.set("isGF", isGFCheckbox.checked ? "true" : "false");
- xml.set("x", Std.string(positionXStepper.value));
- xml.set("y", Std.string(positionYStepper.value));
- xml.set("gameOverChar", gameOverCharTextBox.label.text);
- xml.set("camx", Std.string(cameraXStepper.value));
- xml.set("camy", Std.string(cameraYStepper.value));
- xml.set("holdTime", Std.string(singTimeStepper.value));
- xml.set("flipX", Std.string(flipXCheckbox.checked));
- xml.set("icon", iconTextBox.label.text);
- xml.set("scale", Std.string(scaleStepper.value));
- xml.set("antialiasing", antialiasingCheckbox.checked ? "true" : "false");
- xml.set("sprite", spriteTextBox.label.text);
- if (iconColorWheel.colorChanged)
- xml.set("color", iconColorWheel.curColor.toWebString());
- for (val in customPropertiesButtonList.buttons.members)
- xml.set(val.propertyText.label.text, val.valueText.label.text);
-
- for (anim in character.animDatas)
- {
- var animXml:Xml = Xml.createElement('anim');
- animXml.set("name", anim.name);
- animXml.set("anim", anim.anim);
- animXml.set("loop", Std.string(anim.loop));
- animXml.set("fps", Std.string(anim.fps));
- var offset:FlxPoint = character.getAnimOffset(anim.name);
- animXml.set("x", Std.string(offset.x));
- animXml.set("y", Std.string(offset.y));
- if (anim.indices.length > 0)
- animXml.set("indices", anim.indices.join(","));
- xml.addChild(animXml);
- }
-
- if (onSave != null) onSave(xml);
- }*/
-}
\ No newline at end of file
diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx
index a621dc83..f4f13d70 100644
--- a/source/funkin/game/Stage.hx
+++ b/source/funkin/game/Stage.hx
@@ -57,6 +57,8 @@ class Stage extends FlxBasic implements IBeatReceiver {
if (autoLoad) loadXml(stageXML);
}
+ public static var DEFAULT_ATTRIBUTES:Array = ["name", "startCamPosX", "startCamPosY", "zoom", "folder"];
+
public function loadXml(xml:Access, forceLoadAll:Bool = false) {
if (PlayState.instance == state) {
stageScript = Script.create(Paths.script('data/stages/$stageFile'));
@@ -83,6 +85,11 @@ class Stage extends FlxBasic implements IBeatReceiver {
if (!spritesParentFolder.endsWith("/")) spritesParentFolder += "/";
}
+ // Load custom attributes
+ for(att in xml.x.attributes())
+ if(!DEFAULT_ATTRIBUTES.contains(att))
+ extra.set(att, xml.x.get(att));
+
var elems:Array = [];
// some way to tag that the sprites are from the group
for(node in xml.elements) {