diff --git a/assets/editors/layouts/stage/characterEditScreen.xml b/assets/editors/layouts/stage/characterEditScreen.xml
new file mode 100644
index 00000000..654db6ea
--- /dev/null
+++ b/assets/editors/layouts/stage/characterEditScreen.xml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+ function col(c:Int) {
+ return 20 + (150 + XOFFSET) * c;
+ }
+ previewSprite = null;
+ if(char.animateAtlas == null) {
+ previewSprite = new FunkinSprite(0, 0);
+ previewSprite.frame = char.frame;
+
+ self.add(previewSprite);
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.windowSpr.bHeight -= 170;
+
+
+
+
+ function onUpdate() {
+ if(previewSprite == null) return;
+ previewSprite.skew.x = skewXStepper.value;
+ previewSprite.skew.y = skewYStepper.value;
+ previewSprite.antialiasing = char.antialiasing;
+ var ratio = char.frameWidth / char.frameHeight;
+ previewSprite.setGraphicSize(145 * scaleXStepper.value * ratio, 145 * scaleYStepper.value);
+ previewSprite.updateHitbox();
+ if(flipXCheckbox.checked != (charPos.name == "boyfriend"))
+ previewSprite.scale.x *= -1;
+
+ previewSprite.x = 30;
+ previewSprite.y = self.winHeight - previewSprite.height - 30;
+ }
+
+ function onSave() {
+ setEx("highMemory", highMemoryRadio.checked);
+ setEx("lowMemory", lowMemoryRadio.checked);
+
+ charPos.x = xStepper.value;
+ charPos.y = yStepper.value;
+ charPos.scrollFactor.set(scrollXStepper.value, scrollYStepper.value);
+ charPos.scale.set(scaleXStepper.value, scaleYStepper.value);
+ charPos.camxoffset = camxStepper.value;
+ charPos.camyoffset = camyStepper.value;
+ charPos.skewX = skewXStepper.value;
+ charPos.skewY = skewYStepper.value;
+ charPos.alpha = alphaStepper.value;
+ charPos.charSpacingX = spacingXStepper.value;
+ charPos.charSpacingY = spacingYStepper.value;
+ charPos.flipX = flipXCheckbox.checked;
+ charPos.zoomFactor = zoomFactorStepper.value;
+
+ charPos.revertCharacter(char);
+ charPos.prepareCharacter(char, charPos._id);
+ }
+
+
\ No newline at end of file
diff --git a/assets/editors/layouts/stage/spriteEditScreen.xml b/assets/editors/layouts/stage/spriteEditScreen.xml
index b5bcfd58..534b8598 100644
--- a/assets/editors/layouts/stage/spriteEditScreen.xml
+++ b/assets/editors/layouts/stage/spriteEditScreen.xml
@@ -1,65 +1,74 @@
-
+
- previewSprite = new FunkinSprite(50, self.winHeight - 100);
- previewSprite.frame = sprite.frame;
+ function col(c:Int) {
+ return 20 + (200 + XOFFSET) * c;
+ }
- self.add(previewSprite);
+ if(sprite.animateAtlas == null) {
+ previewSprite = new FunkinSprite(50, self.winHeight - 100);
+ previewSprite.frame = sprite.frame;
+
+ self.add(previewSprite);
+ }
-
-
+
+
-
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
+
function onUpdate() {
- previewSprite.color = 0xFFFFFFFF;
+ if(previewSprite == null) return;
+ previewSprite.color = 0xFFFFFFFF; // TODO: Color Wheel
previewSprite.skew.x = skewXStepper.value;
previewSprite.skew.y = skewYStepper.value;
previewSprite.angle = angleStepper.value;
@@ -85,34 +94,34 @@
sprite.angle = angleStepper.value;
function saveXY(obj:Dynamic, name:String, x:UINumericStepper, y:UINumericStepper) {
- data.xml.remove(name + "");
- data.xml.remove(name + "x");
- data.xml.remove(name + "y");
+ button.xml.remove(name + "");
+ button.xml.remove(name + "x");
+ button.xml.remove(name + "y");
obj.x = x.value;
obj.y = y.value;
if(x.value == y.value)
- data.xml.set(name, x.value);
+ button.xml.set(name, x.value);
else {
- data.xml.set(name + "x", x.value);
- data.xml.set(name + "y", y.value);
+ button.xml.set(name + "x", x.value);
+ button.xml.set(name + "y", y.value);
}
}
- data.xml.set("name", nameTextBox.label.text);
- data.xml.set("sprite", spriteTextBox.label.text);
- data.xml.set("x", xStepper.value);
- data.xml.set("y", yStepper.value);
- data.xml.set("zoom", zoomFactorStepper.value);
- data.xml.set("type", animType.key);
- data.xml.set("antialiasing", antialiasingCheckbox.checked);
- data.xml.set("angle", angleStepper.value);
+ button.xml.set("name", nameTextBox.label.text);
+ button.xml.set("sprite", spriteTextBox.label.text);
+ button.xml.set("x", xStepper.value);
+ button.xml.set("y", yStepper.value);
+ button.xml.set("zoom", zoomFactorStepper.value);
+ button.xml.set("type", animType.key);
+ button.xml.set("antialiasing", antialiasingCheckbox.checked);
+ button.xml.set("angle", angleStepper.value);
saveXY(sprite.scrollFactor, "scroll", scrollXStepper, scrollYStepper);
saveXY(sprite.scale, "scale", scaleXStepper, scaleYStepper);
saveXY(sprite.skew, "skew", skewXStepper, skewYStepper);
- XMLUtil.loadSpriteFromXML(sprite, data.xml, stage.spritesParentFolder);
+ XMLUtil.loadSpriteFromXML(sprite, button.xml, stage.spritesParentFolder);
}
\ No newline at end of file
diff --git a/source/funkin/editors/stage/StageEditor.hx b/source/funkin/editors/stage/StageEditor.hx
index 51896319..e094cf4f 100644
--- a/source/funkin/editors/stage/StageEditor.hx
+++ b/source/funkin/editors/stage/StageEditor.hx
@@ -1,6 +1,5 @@
package funkin.editors.stage;
-import lime.ui.MouseCursor;
import flixel.math.FlxAngle;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
@@ -9,11 +8,13 @@ import flixel.util.FlxSort;
import funkin.backend.system.framerate.Framerate;
import funkin.backend.utils.XMLUtil.AnimData;
import funkin.editors.stage.elements.*;
+import funkin.editors.stage.elements.StageSpriteButton.StageSpriteEditScreen;
import funkin.editors.ui.UIContextMenu.UIContextMenuOption;
import funkin.game.Character;
import funkin.game.Stage;
import haxe.xml.Access;
import haxe.xml.Printer;
+import lime.ui.MouseCursor;
import openfl.ui.Mouse;
using funkin.backend.utils.MatrixUtil;
@@ -78,11 +79,6 @@ class StageEditor extends UIState {
{
label: "File",
childs: [
- {
- label: "New",
- onSelect: _file_new,
- },
- null,
{
label: "Save",
keybind: [CONTROL, S],
@@ -215,6 +211,7 @@ class StageEditor extends UIState {
}
}
stage.onNodeLoaded = function(node:Access, sprite:Dynamic):Dynamic {
+ var parent = new Access(node.x.parent);
var name = "";
if(sprite is FlxSprite) {
//sprite.forceIsOnScreen = true; // hack
@@ -225,7 +222,6 @@ 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");
@@ -254,10 +250,17 @@ class StageEditor extends UIState {
// Add it to the stage
char.visible = true;
char.alpha = 0.5;
- char.extra.set(exID("node"), node);
- char.extra.set(exID("pos"), charPos);
- charPos.extra.set(exID("node"), node);
- charPos.extra.set(exID("char"), char);
+ function setEx(name:String, value:Dynamic) {
+ char.extra.set(exID(name), value);
+ charPos.extra.set(exID(name), value);
+ }
+ setEx("node", node);
+ setEx("pos", charPos);
+ setEx("char", char);
+
+ setEx("parentNode", parent);
+ setEx("highMemory", parent.name == "highMemory");
+ setEx("lowMemory", parent.name == "lowMemory");
chars.push(char);
}
order.push(sprite);
@@ -307,12 +310,12 @@ class StageEditor extends UIState {
sprite.extra.set(exID("node"), node);
sprite.extra.set(exID("type"), node.name);
sprite.extra.set(exID("imageFile"), '');
- sprite.extra.set(exID("parentNode"), stage.stageXML.x);
+ sprite.extra.set(exID("parentNode"), new Access(node.x.parent));
sprite.extra.set(exID("highMemory"), false);
sprite.extra.set(exID("lowMemory"), false);
xmlMap.set(sprite, node);
- var button:StageElementButton = new StageSpriteButton(0, 0, sprite, node);
+ var button:StageSpriteButton = new StageSpriteButton(0, 0, sprite, node);
sprite.extra.set(exID("button"), button);
stageSpritesWindow.add(button);
@@ -477,9 +480,6 @@ class StageEditor extends UIState {
else FlxG.switchState(new StageSelection());
}
- function _file_new(_) {
- }
-
function _file_save(_) {
#if sys
CoolUtil.safeSaveFile(
@@ -506,6 +506,7 @@ class StageEditor extends UIState {
}
function savePointToXml(xml:Xml, name:String, point:FlxPoint, ?defaultValueX:Float, ?defaultValueY:Float) {
if (point == null) return xml;
+ if(defaultValueY == null) defaultValueY = defaultValueX;
if(point.x == point.y) {
saveToXml(xml, name, point.x, defaultValueX);
} else {
@@ -545,8 +546,8 @@ class StageEditor extends UIState {
saveToXml(spriteXML, "x", sprite.x, 0);
saveToXml(spriteXML, "y", sprite.y, 0);
saveToXml(spriteXML, "sprite", sprite.extra.get(exID("imageFile")));
- savePointToXml(spriteXML, "scale", sprite.scale, 1, 1);
- savePointToXml(spriteXML, "scroll", sprite.scrollFactor, 0, 0);
+ savePointToXml(spriteXML, "scale", sprite.scale, 1);
+ savePointToXml(spriteXML, "scroll", sprite.scrollFactor, 0);
saveToXml(spriteXML, "skewx", sprite.skew.x, 0);
saveToXml(spriteXML, "skewy", sprite.skew.y, 0);
saveToXml(spriteXML, "alpha", sprite.alpha, 1);
@@ -590,9 +591,10 @@ class StageEditor extends UIState {
saveToXml(charXML, "spacingx", charPos.charSpacingX, 20);
saveToXml(charXML, "spacingy", charPos.charSpacingY, 0);
saveToXml(charXML, "alpha", charPos.alpha, 1);
+ saveToXml(charXML, "zoomfactor", charPos.zoomFactor, 1);
saveToXml(charXML, "flipX", charPos.flipX, defaultPos.flip);
- savePointToXml(charXML, "scroll", charPos.scrollFactor, defaultPos.scroll, defaultPos.scroll);
- savePointToXml(charXML, "scale", charPos.scale, 1, 1);
+ savePointToXml(charXML, "scroll", charPos.scrollFactor, defaultPos.scroll);
+ savePointToXml(charXML, "scale", charPos.scale, 1);
xml.addChild(charXML);
} else {
Logs.trace("Unknown Stage Type : " + Type.getClassName(Type.getClass(button)));
@@ -791,7 +793,7 @@ class StageEditor extends UIState {
for(char in chars) {
var button:StageCharacterButton = char.extra.get(exID("button"));
button.isHidden = !showCharacters;
- button.updateInfo(button.charPos);
+ button.updateInfo();
}
}
#end
@@ -972,7 +974,7 @@ class StageEditor extends UIState {
// todo: make this origin based
relative.rotateByDegrees(sprite.angle);
call(mouseMode.toString(), [sprite, relative]);
- cast(sprite.extra.get(exID("button")), StageElementButton).updateInfo(sprite);
+ cast(sprite.extra.get(exID("button")), StageElementButton).updateInfo();
relative.put();
}
diff --git a/source/funkin/editors/stage/StageSpriteEditScreen.hx b/source/funkin/editors/stage/StageSpriteEditScreen.hx
deleted file mode 100644
index d1b4cf18..00000000
--- a/source/funkin/editors/stage/StageSpriteEditScreen.hx
+++ /dev/null
@@ -1,49 +0,0 @@
-package funkin.editors.stage;
-
-import funkin.editors.stage.elements.StageElementButton;
-import funkin.editors.ui.UISoftcodedWindow;
-
-using StringTools;
-
-
-class StageSpriteEditScreen extends UISoftcodedWindow {
- public var newSprite:Bool = false;
- public var data:StageElementButton;
- public var sprite:FunkinSprite;
- var isSaving:Bool = false;
-
- public function new(data:StageElementButton) {
- this.data = data;
- this.sprite = data.getSprite();
- super("layouts/stage/spriteEditScreen.xml", [
- "stage" => StageEditor.instance.stage,
- "sprite" => sprite,
- "data" => data,
- "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);
- },
- ]);
- }
-
- public override function create() {
- super.create();
- }
-
- public override function saveData() {
- isSaving = true;
- super.saveData();
- data.updateInfo(sprite);
- }
-
- public override function close() {
- if (!isSaving && newSprite) {
- data.onDelete();
- trace("deleting sprite");
- }
- super.close();
- }
-}
\ No newline at end of file
diff --git a/source/funkin/editors/stage/elements/StageCharacterButton.hx b/source/funkin/editors/stage/elements/StageCharacterButton.hx
index 905cdc99..e28e89d3 100644
--- a/source/funkin/editors/stage/elements/StageCharacterButton.hx
+++ b/source/funkin/editors/stage/elements/StageCharacterButton.hx
@@ -15,7 +15,7 @@ class StageCharacterButton extends StageElementButton {
color = 0xff7aa8ff;
- updateInfo(charPos);
+ updateInfo();
}
public override function update(elapsed:Float) {
@@ -27,13 +27,10 @@ class StageCharacterButton extends StageElementButton {
super.update(elapsed);
}
- public override function updateInfo(charPos:Dynamic) {
- if(charPos is StageCharPos) {
- var charPos:StageCharPos = cast charPos;
- this.charPos = charPos;
- char.visible = !isHidden;
- }
- super.updateInfo(charPos);
+ public override function updateInfo() {
+ char.visible = !isHidden;
+ char.alpha = 0.5 * charPos.alpha;
+ super.updateInfo();
}
public override function getSprite():FunkinSprite {
@@ -46,13 +43,17 @@ class StageCharacterButton extends StageElementButton {
}
public override function onEdit() {
- UIState.state.displayNotification(new UIBaseNotification("Editing a character isnt implemented yet!", 2, BOTTOM_LEFT));
- CoolUtil.playMenuSFX(WARNING, 0.45);
+ FlxG.state.openSubState(new StageCharacterEditScreen(this));
}
+ //public override function onEdit() {
+ // UIState.state.displayNotification(new UIBaseNotification("Editing a character isnt implemented yet!", 2, BOTTOM_LEFT));
+ // CoolUtil.playMenuSFX(WARNING, 0.45);
+ //}
+
public override function onGhostClick() {
isHidden = !isHidden;
- updateInfo(this.charPos);
+ updateInfo();
}
public override function getName():String {
@@ -66,4 +67,38 @@ class StageCharacterButton extends StageElementButton {
public override function updatePos() {
super.updatePos();
}
+}
+
+class StageCharacterEditScreen extends UISoftcodedWindow {
+ public var button:StageCharacterButton;
+ public var char:Character;
+ public var charPos:StageCharPos;
+
+ public function new(button:StageCharacterButton) {
+ this.button = button;
+ this.char = button.char;
+ this.charPos = button.charPos;
+ super("layouts/stage/characterEditScreen.xml", [
+ "stage" => StageEditor.instance.stage,
+ "char" => char,
+ "charPos" => charPos,
+ "button" => button,
+ "exID" => StageEditor.exID,
+ "getEx" => function(name:String):Dynamic {
+ return char.extra.get(StageEditor.exID(name));
+ },
+ "setEx" => function(name:String, value:Dynamic) {
+ char.extra.set(StageEditor.exID(name), value);
+ },
+ ]);
+ }
+
+ public override function create() {
+ super.create();
+ }
+
+ public override function saveData() {
+ super.saveData();
+ button.updateInfo();
+ }
}
\ No newline at end of file
diff --git a/source/funkin/editors/stage/elements/StageElementButton.hx b/source/funkin/editors/stage/elements/StageElementButton.hx
index 49194d5d..11f3edf1 100644
--- a/source/funkin/editors/stage/elements/StageElementButton.hx
+++ b/source/funkin/editors/stage/elements/StageElementButton.hx
@@ -122,7 +122,7 @@ class StageElementButton extends UIButton {
}
}
- public function updateInfo(sprite:Dynamic) {
+ public function updateInfo() {
field.text = getInfoText();
ghostIcon.animation.play(!isHidden ? "alive" : "dead");
diff --git a/source/funkin/editors/stage/elements/StageSpriteButton.hx b/source/funkin/editors/stage/elements/StageSpriteButton.hx
index 09cc061e..5c584548 100644
--- a/source/funkin/editors/stage/elements/StageSpriteButton.hx
+++ b/source/funkin/editors/stage/elements/StageSpriteButton.hx
@@ -1,8 +1,9 @@
package funkin.editors.stage.elements;
-import haxe.xml.Access;
-import funkin.editors.stage.StageSpriteEditScreen;
import flixel.util.FlxColor;
+import funkin.editors.stage.elements.StageElementButton;
+import funkin.editors.ui.UISoftcodedWindow;
+import haxe.xml.Access;
class StageSpriteButton extends StageElementButton {
public var sprite:FunkinSprite;
@@ -13,20 +14,16 @@ class StageSpriteButton extends StageElementButton {
//color = 0xFFD9FF50;
- updateInfo(sprite);
+ updateInfo();
}
public override function update(elapsed:Float) {
super.update(elapsed);
}
- public override function updateInfo(sprite:Dynamic) {
- if(sprite is FunkinSprite) {
- var sprite:FunkinSprite = cast sprite;
- this.sprite = sprite;
- sprite.visible = !isHidden;
- }
- super.updateInfo(sprite);
+ public override function updateInfo() {
+ sprite.visible = !isHidden;
+ super.updateInfo();
}
public override function getSprite():FunkinSprite {
@@ -39,11 +36,10 @@ class StageSpriteButton extends StageElementButton {
public override function onGhostClick() {
isHidden = !isHidden;
- updateInfo(this.sprite);
+ updateInfo();
}
public override function onEdit() {
- // TODO: implement
FlxG.state.openSubState(new StageSpriteEditScreen(this));
}
@@ -66,4 +62,46 @@ class StageSpriteButton extends StageElementButton {
public override function updatePos() {
super.updatePos();
}
+}
+
+class StageSpriteEditScreen extends UISoftcodedWindow {
+ public var newSprite:Bool = false;
+ public var button:StageSpriteButton;
+ public var sprite:FunkinSprite;
+ var isSaving:Bool = false;
+
+ public function new(button:StageSpriteButton) {
+ this.button = button;
+ this.sprite = button.getSprite();
+ super("layouts/stage/spriteEditScreen.xml", [
+ "stage" => StageEditor.instance.stage,
+ "sprite" => sprite,
+ "button" => button,
+ "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);
+ },
+ ]);
+ }
+
+ public override function create() {
+ super.create();
+ }
+
+ public override function saveData() {
+ isSaving = true;
+ super.saveData();
+ button.updateInfo();
+ }
+
+ public override function close() {
+ if (!isSaving && newSprite) {
+ button.onDelete();
+ trace("deleting sprite");
+ }
+ super.close();
+ }
}
\ No newline at end of file
diff --git a/source/funkin/editors/ui/UISoftcodedWindow.hx b/source/funkin/editors/ui/UISoftcodedWindow.hx
index ff751fec..5e0c71b9 100644
--- a/source/funkin/editors/ui/UISoftcodedWindow.hx
+++ b/source/funkin/editors/ui/UISoftcodedWindow.hx
@@ -71,7 +71,7 @@ class UISoftcodedWindow extends UISubstateWindow {
return CoolUtil.getDefault(exec(code), defaultValue);
}
- function execAtt(el:Access, key:String, defaultValue:Dynamic):Dynamic {
+ function execAtt(el:Access, key:String, ?defaultValue:Dynamic):Dynamic {
return execDefault(el.getAtt(key), defaultValue);
}
@@ -101,9 +101,6 @@ class UISoftcodedWindow extends UISubstateWindow {
public override function create() {
var layout = new Access(Xml.parse(Assets.getText('assets/editors/' + xmlPath)).firstElement());
- winTitle = layout.getAtt("title").getDefault(winTitle);
- winWidth = Std.parseInt(layout.getAtt("width")).getDefault(winWidth);
- winHeight = Std.parseInt(layout.getAtt("height")).getDefault(winHeight);
for(k=>e in Script.getDefaultVariables()) {
set(k, e);
@@ -119,110 +116,134 @@ class UISoftcodedWindow extends UISubstateWindow {
}
set("last", null);
+ winTitle = execString(layout.getAtt("title").getDefault(winTitle));
+ winWidth = Std.parseInt(layout.getAtt("width")).getDefault(winWidth);
+ winHeight = Std.parseInt(layout.getAtt("height")).getDefault(winHeight);
+
super.create();
function addLabelOn(ui:UISprite, text:String)
add(new UIText(ui.x, ui.y - 24, 0, text));
- for(el in layout.elements) {
- var type = el.name;
- //var type:String = el.getAtt("type");
- var name:String = execString(el.getAtt("name"));
- var label:String = execString(el.getAtt("label"));
- var text:String = execString(el.getAtt("text"));
- var x:Float = execAtt(el, "x", 0);
- var y:Float = execAtt(el, "y", 0);
- var width:Null = exec(el.getAtt("width"));
- var height:Null = exec(el.getAtt("height"));
- var size:Int = execAtt(el, "size", 28);
-
- trace(type, name, label, text, x, y, width, height, size);
-
- var sprite:FlxSprite = switch(type) {
- case "set":
- set(execString(el.getAtt("name")), exec(el.getAtt("value")));
- continue;
- case "image":
- var spr = XMLUtil.createSpriteFromXML(el, "", LOOP);
- cast add(spr);
- case "solid":
- var spr = new FunkinSprite(x, y).makeSolid(
- execAtt(el, "width", 100),
- execAtt(el, "height", 100),
- execAtt(el, "color", 0xFFFFFFFF)
- );
- cast add(spr);
- case "exec":
- exec(el.innerData);
- continue;
- case "textbox":
- var textBox = new UITextBox(x, y, text, width, height, execAtt(el, "multiline", false));//(el.getAtt("multiline").getDefault("false") == "true"));
- add(textBox);
- addLabelOn(textBox, label);
- textBox;
- case "title":
- cast add(new UIText(x, y, 0, text, size));
- case "stepper":
- // x:Float, y:Float, value:Float = 0, step:Float = 1, precision:Int = 0, ?min:Float, ?max:Float, w:Int = 180, h:Int = 32
- var stepper = new UINumericStepper(
- x,
- y,
- execAtt(el, "value", 0),
- execAtt(el, "step", 1),
- execAtt(el, "precision", 0),
- execAtt(el, "min", null),
- execAtt(el, "max", null),
- width,
- height
- );
- add(stepper);
- addLabelOn(stepper, label);
- stepper;
- case "checkbox":
- var checkbox = new UICheckbox(x, y, text, execAtt(el, "value", false));
- 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);
- addLabelOn(slider, label);
- slider;
- case "dropdown":
- var items:Array = [];
- for(i=>node in el.nodes.item)
- items.push({label: execString(node.getAtt("label")), value: execAtt(node, "value", i)});
- var curValue = execAtt(el, "value", null);
- var index = UIDropDown.indexOfItemValue(items, curValue);
- if (index == -1) index = 0;
-
- var dropdown = new UIDropDown(x, y, width, height, items, index);
- add(dropdown);
- addLabelOn(dropdown, label);
- dropdown;
- // UIColorwheel
- // UIAudioPlayer
- // UIButtonList
- // UIFileExplorer
- // UIAutoCompleteTextbox
- default: {
- Logs.trace("Unknown element type: " + type, ERROR, RED);
- Logs.trace("Skipping element: " + el.x.toString(), ERROR, RED);
- continue;
- }
- }
-
- set("last", sprite);
- if(name != null) set(name, sprite);
- if(sprite is UISprite) elementMap.set(name, cast sprite);
+ function getArr(i:Iterator) {
+ return [for(e in i) e];
}
+ function addLayout(elements:Array) {
+ for(el in elements) {
+ var type = el.name;
+
+ switch(type) {
+ case "section":
+ if(execAtt(el, "if", true) != true)
+ continue;
+ if(execAtt(el, "unless", false) != false)
+ continue;
+ addLayout(getArr(el.elements));
+ continue;
+ case "set":
+ set(execString(el.getAtt("name")), execAtt(el, "value"));
+ continue;
+ case "exec":
+ exec(el.innerData);
+ continue;
+ }
+
+ var name:String = execString(el.getAtt("name"));
+ var label:String = execString(el.getAtt("label"));
+ var x:Float = execAtt(el, "x", 0);
+ var y:Float = execAtt(el, "y", 0);
+
+ var sprite:FlxSprite = switch(type) {
+ case "image":
+ var spr = XMLUtil.createSpriteFromXML(el, "", LOOP);
+ spr.x = x;
+ spr.y = y;
+ cast add(spr);
+ case "solid":
+ var spr = new FunkinSprite(x, y).makeSolid(
+ execAtt(el, "width", 100),
+ execAtt(el, "height", 100),
+ execAtt(el, "color", 0xFFFFFFFF)
+ );
+ cast add(spr);
+ case "textbox":
+ var text:String = execString(el.getAtt("text"));
+ text = Std.string(execAtt(el, "value", text));
+ var textBox = new UITextBox(x, y, text, execAtt(el, "width"), execAtt(el, "height"), execAtt(el, "multiline", false));//(el.getAtt("multiline").getDefault("false") == "true"));
+ add(textBox);
+ addLabelOn(textBox, label);
+ textBox;
+ case "title":
+ cast add(new UIText(x, y, 0, execString(el.getAtt("text")), execAtt(el, "size", 28)));
+ case "label":
+ cast add(new UIText(x, y - 24, 0, execString(el.getAtt("text")), execAtt(el, "size", 15)));
+ case "text":
+ cast add(new UIText(x, y, 0, execString(el.getAtt("text")), execAtt(el, "size", 15)));
+ case "stepper":
+ // x:Float, y:Float, value:Float = 0, step:Float = 1, precision:Int = 0, ?min:Float, ?max:Float, w:Int = 180, h:Int = 32
+ var stepper = new UINumericStepper(
+ x,
+ y,
+ execAtt(el, "value", 0),
+ execAtt(el, "step", 1),
+ execAtt(el, "precision", 0),
+ execAtt(el, "min"),
+ execAtt(el, "max"),
+ execAtt(el, "width"),
+ execAtt(el, "height")
+ );
+ add(stepper);
+ addLabelOn(stepper, label);
+ stepper;
+ case "checkbox":
+ var checkbox = new UICheckbox(x, y, execString(el.getAtt("text")), execAtt(el, "value", false));
+ add(checkbox);
+ addLabelOn(checkbox, label);
+ checkbox;
+ case "radio":
+ var radio = new UIRadioButton(x, y, execString(el.getAtt("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, execAtt(el, "width"), execAtt(el, "value", 0), execAtt(el, "segments", []), execAtt(el, "centered", false));
+ add(slider);
+ addLabelOn(slider, label);
+ slider;
+ case "dropdown":
+ var items:Array = [];
+ for(i=>node in el.nodes.item)
+ items.push({label: execString(node.getAtt("label")), value: execAtt(node, "value", i)});
+ var curValue = execAtt(el, "value");
+ var index = UIDropDown.indexOfItemValue(items, curValue);
+ if (index == -1) index = 0;
+
+ var dropdown = new UIDropDown(x, y, execAtt(el, "width"), execAtt(el, "height"), items, index);
+ add(dropdown);
+ addLabelOn(dropdown, label);
+ dropdown;
+ // UIColorwheel
+ // UIAudioPlayer
+ // UIButtonList
+ // UIFileExplorer
+ // UIAutoCompleteTextbox
+ default: {
+ Logs.trace("Unknown element type: " + type, ERROR, RED);
+ Logs.trace("Skipping element: " + el.x.toString(), ERROR, RED);
+ continue;
+ }
+ }
+
+ set("last", sprite);
+ if(name != null) set(name, sprite);
+ if(sprite is UISprite) elementMap.set(name, cast sprite);
+ }
+ }
+
+ addLayout(getArr(layout.elements));
+
if(get("hasSaveButtons")) {
saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, windowSpr.y + windowSpr.bHeight - 20, "Save & Close", function() {
saveData();
diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx
index 9d066a23..6a98e173 100644
--- a/source/funkin/game/Stage.hx
+++ b/source/funkin/game/Stage.hx
@@ -249,6 +249,7 @@ class Stage extends FlxBasic implements IBeatReceiver {
charPos.skewY = Std.parseFloat(node.getAtt("skewy")).getDefault(charPos.skewY);
charPos.alpha = Std.parseFloat(node.getAtt("alpha")).getDefault(charPos.alpha);
charPos.flipX = (node.has.flip || node.has.flipX) ? (node.getAtt("flip") == "true" || node.getAtt("flipX") == "true") : charPos.flipX;
+ charPos.zoomFactor = Std.parseFloat(node.getAtt("zoomfactor")).getDefault(charPos.zoomFactor);
if (node.has.scale) {
var scale:Null = Std.parseFloat(node.att.scale);
@@ -337,6 +338,7 @@ class StageCharPos extends FlxObject {
public var alpha:Float = 1;
public var flipX:Bool = false;
public var scale:FlxPoint = FlxPoint.get(1, 1);
+ public var zoomFactor:Float = 1;
public function new() {
super();
@@ -349,13 +351,49 @@ class StageCharPos extends FlxObject {
super.destroy();
}
+ private var _id:Float = -1;
+
+ private var oldInfo:OldCharInfo = null;
+
public function prepareCharacter(char:Character, id:Float = 0) {
+ _id = id;
+ oldInfo = getOldInfo(char);
char.setPosition(x + (id * charSpacingX), y + (id * charSpacingY));
char.scrollFactor.set(scrollFactor.x, scrollFactor.y);
char.scale.x *= scale.x; char.scale.y *= scale.y;
char.cameraOffset += FlxPoint.weak(camxoffset, camyoffset);
char.skew.x += skewX; char.skew.y += skewY;
char.alpha *= alpha;
+ char.zoomFactor *= zoomFactor;
+ }
+
+ public function getOldInfo(char:Character) {
+ return {
+ x: char.x, y: char.y,
+ scrollX: char.scrollFactor.x, scrollY: char.scrollFactor.y,
+ scaleX: char.scale.x, scaleY: char.scale.y,
+ camxoffset: char.cameraOffset.x, camyoffset: char.cameraOffset.y,
+ skewX: char.skew.x, skewY: char.skew.y,
+ alpha: char.alpha, zoomFactor: char.zoomFactor
+ }
+ }
+
+ public function revertCharacter(char:Character) {
+ if(oldInfo == null) return;
+ for(field in Reflect.fields(oldInfo)) {
+ switch(field) {
+ case "scrollX": char.scrollFactor.x = oldInfo.scrollX;
+ case "scrollY": char.scrollFactor.y = oldInfo.scrollY;
+ case "scaleX": char.scale.x = oldInfo.scaleX;
+ case "scaleY": char.scale.y = oldInfo.scaleY;
+ case "camxoffset": char.cameraOffset.x = oldInfo.camxoffset;
+ case "camyoffset": char.cameraOffset.y = oldInfo.camyoffset;
+ case "skewX": char.skew.x = oldInfo.skewX;
+ case "skewY": char.skew.y = oldInfo.skewY;
+ default: Reflect.setField(char, field, Reflect.field(oldInfo, field));
+ }
+ }
+ oldInfo = null;
}
}
typedef StageCharPosInfo = {
@@ -363,4 +401,19 @@ typedef StageCharPosInfo = {
var y:Float;
var flip:Bool;
var scroll:Float;
+}
+
+typedef OldCharInfo = {
+ var x:Float;
+ var y:Float;
+ var scrollX:Float;
+ var scrollY:Float;
+ var scaleX:Float;
+ var scaleY:Float;
+ var camxoffset:Float;
+ var camyoffset:Float;
+ var skewX:Float;
+ var skewY:Float;
+ var alpha:Float;
+ var zoomFactor:Float;
}
\ No newline at end of file