diff --git a/assets/data/stages/test.xml b/assets/data/stages/test.xml index 82cfbadd..be041748 100644 --- a/assets/data/stages/test.xml +++ b/assets/data/stages/test.xml @@ -7,4 +7,6 @@ + + \ No newline at end of file diff --git a/assets/editors/layouts/stage/spriteEditScreen.xml b/assets/editors/layouts/stage/spriteEditScreen.xml index 534b8598..611e5feb 100644 --- a/assets/editors/layouts/stage/spriteEditScreen.xml +++ b/assets/editors/layouts/stage/spriteEditScreen.xml @@ -18,45 +18,52 @@ - <set name="curY" value="title.y + TO" /> <!-- ROW 1 --> + <section> <!-- ROW 1 --> + <set name="curY" value="title.y + TO" /> - <textbox name="nameTextBox" label="Name Identifier" value="button.getName()" x="col(0)" y="curY" width="200" height="32" /> - <textbox name="spriteTextBox" label="Image File (${stage.spritesParentFolder})" value="getEx('imageFile')" x="last.x + last.bWidth + XOFFSET" y="curY" width="200" height="32" /> + <textbox name="nameTextBox" label="Name Identifier" value="button.getName()" x="col(0)" y="curY" width="200" height="32" /> + <textbox name="spriteTextBox" label="Image File (${stage.spritesParentFolder})" value="getEx('imageFile')" x="last.x + last.bWidth + XOFFSET" y="curY" width="200" height="32" /> + </section> - <set name="curY" value="nameTextBox.y + nameTextBox.bHeight + YOFFSET" /> <!-- ROW 2 --> + <section> <!-- ROW 2 --> + <set name="curY" value="nameTextBox.y + nameTextBox.bHeight + YOFFSET" /> - <stepper name="xStepper" label="X" value="sprite.x" x="col(0)" y="curY" step="1" width="100" /> - <stepper name="yStepper" label="Y" value="sprite.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" step="1" width="100" /> + <stepper name="xStepper" label="X" value="sprite.x" x="col(0)" y="curY" step="1" width="100" /> + <stepper name="yStepper" label="Y" value="sprite.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" step="1" width="100" /> - <stepper name="scrollXStepper" label="Scroll X" value="sprite.scrollFactor.x" x="spriteTextBox.x" y="curY" precision="2" step="0.01" width="100" /> - <stepper name="scrollYStepper" label="Scroll Y" value="sprite.scrollFactor.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="scrollXStepper" label="Scroll X" value="sprite.scrollFactor.x" x="spriteTextBox.x" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="scrollYStepper" label="Scroll Y" value="sprite.scrollFactor.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> - <stepper name="scaleXStepper" label="Scale X" value="sprite.scale.x" x="col(2)" y="curY" precision="2" step="0.01" width="100" /> - <stepper name="scaleYStepper" label="Scale Y" value="sprite.scale.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="scaleXStepper" label="Scale X" value="sprite.scale.x" x="col(2)" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="scaleYStepper" label="Scale Y" value="sprite.scale.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> + </section> - <set name="curY" value="xStepper.y + xStepper.bHeight + YOFFSET" /> <!-- ROW 3 --> + <section> <!-- ROW 3 --> + <set name="curY" value="xStepper.y + xStepper.bHeight + YOFFSET" /> - <stepper name="angleStepper" label="Angle" value="sprite.angle" x="col(0)" y="curY" precision="2" step="0.01" width="100" /> - <stepper name="zoomFactorStepper" label="Zoom Factor" value="sprite.zoomFactor" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="angleStepper" label="Angle" value="sprite.angle" x="col(0)" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="zoomFactorStepper" label="Zoom Factor" value="sprite.zoomFactor" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> - <!-- TODO: Simplify this --> - <dropdown name="animType" label="Animation Type" value="sprite.spriteAnimType" x="col(1)" y="curY" width="150" height="32"> - <item label="NONE" value="0" /> - <item label="BEAT" value="1" /> - <item label="LOOP" value="2" /> - </dropdown> + <!-- TODO: Simplify this --> + <dropdown name="animType" label="Animation Type" value="sprite.spriteAnimType" x="col(1)" y="curY" width="150" height="32"> + <item label="NONE" value="0" /> + <item label="BEAT" value="1" /> + <item label="LOOP" value="2" /> + </dropdown> - <stepper name="skewXStepper" label="Skew X" value="sprite.skew.x" x="col(2)" y="curY" precision="2" step="0.01" width="100" /> - <stepper name="skewYStepper" label="Skew Y" value="sprite.skew.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="skewXStepper" label="Skew X" value="sprite.skew.x" x="col(2)" y="curY" precision="2" step="0.01" width="100" /> + <stepper name="skewYStepper" label="Skew Y" value="sprite.skew.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" /> + </section> - <!-- ROW 4 --> - <set name="curY" value="angleStepper.y + angleStepper.bHeight + YOFFSET" /> + <section> <!-- ROW 4 --> + <set name="curY" value="angleStepper.y + angleStepper.bHeight + YOFFSET" /> - <checkbox name="antialiasingCheckbox" text="Antialiasing" value="sprite.antialiasing" x="col(0)" y="curY" /> - <radio for="memoryCheck" name="highMemoryRadio" text="High Memory Only" value="getEx('highMemory')" x="col(1)" y="curY" /> - <radio for="memoryCheck" name="lowMemoryRadio" text="Low Memory Only" value="getEx('lowMemory')" x="col(2)" y="curY" /> + <checkbox name="antialiasingCheckbox" text="Antialiasing" value="sprite.antialiasing" x="col(0)" y="curY" /> + <radio for="memoryCheck" name="highMemoryRadio" text="High Memory Only" value="getEx('highMemory')" x="col(1)" y="curY" /> + <radio for="memoryCheck" name="lowMemoryRadio" text="Low Memory Only" value="getEx('lowMemory')" x="col(2)" y="curY" /> - <!-- TODO: Animation list --> + <!-- TODO: Animation list --> + </section> <!-- Preview Transform --> diff --git a/assets/editors/layouts/stage/unknownEditScreen.xml b/assets/editors/layouts/stage/unknownEditScreen.xml index 4c053731..b2b54542 100644 --- a/assets/editors/layouts/stage/unknownEditScreen.xml +++ b/assets/editors/layouts/stage/unknownEditScreen.xml @@ -1,15 +1,16 @@ -<window width="310" height="570" title="Editing XML <${button.getName()} />"> +<window width="350" height="570" title="Editing XML <${button.getName()} />"> + <set name="MARGIN" value="20" /> <set name="XOFFSET" value="30" /> <set name="YOFFSET" value="40" /> <set name="TO" value="64" /> <exec> function col(c:Int) { - return 20 + (150 + XOFFSET) * c; + return MARGIN + (150 + XOFFSET) * c; } </exec> - <title name="title" x="20" y="30 + 16" text="Xml Data" /> + <title name="title" x="MARGIN" y="30 + 16" text="Xml Data" /> <section> <set name="curY" value="title.y + TO" /> @@ -17,16 +18,36 @@ <textbox name="nodeNameTextBox" label="Element Name" value="button.getName()" x="col(0)" y="curY" width="280" height="32" /> </section> <section> - <set name="curY" value="nodeNameTextBox.y + nodeNameTextBox.bHeight + YOFFSET - 20" /> + <set name="curY" value="nodeNameTextBox.y + nodeNameTextBox.bHeight + YOFFSET - 30" /> <radio for="memoryCheck" name="highMemoryRadio" text="High Memory Only" value="button.highMemory" x="col(0)" y="curY" /> <radio for="memoryCheck" name="lowMemoryRadio" text="Low Memory Only" value="button.lowMemory" x="col(0)" y="last.y + last.check.height + YOFFSET - 30" /> </section> <section> - <set name="curY" value="lowMemoryRadio.y + lowMemoryRadio.check.height + YOFFSET - 20" /> + <set name="curY" value="lowMemoryRadio.y + lowMemoryRadio.check.height + YOFFSET" /> + <set name="listWidth" value="self.winWidth - MARGIN * 2" /> - <!-- TODO: attribute button list --> + <buttonlist name="attributesList" label="Attributes" x="col(0)" y="curY" width="listWidth" height="260" buttonSizeX="listWidth-10" buttonSizeY="35" buttonSpacing="5"> + <texture path="editors/ui/inputbox" /> + <camSpacing value="0" /> + + <code> + 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, 110, 145, 25)); + } + + for (i in xml.attributes()) + buttonList.add(new PropertyButton(i, xml.get(i), buttonList, width, height, 110, 145, 25)); + </code> + </buttonlist> </section> <exec> @@ -34,6 +55,9 @@ button.xml.nodeName = nodeNameTextBox.label.text; button.highMemory = highMemoryRadio.checked; button.lowMemory = lowMemoryRadio.checked; + + for (val in attributesList.buttons.members) + xml.set(val.propertyText.label.text, val.valueText.label.text); } </exec> </window> \ No newline at end of file diff --git a/source/funkin/editors/extra/PropertyButton.hx b/source/funkin/editors/extra/PropertyButton.hx index 0ffad946..4cf5a9c3 100644 --- a/source/funkin/editors/extra/PropertyButton.hx +++ b/source/funkin/editors/extra/PropertyButton.hx @@ -6,28 +6,36 @@ class PropertyButton extends UIButton { public var deleteButton:UIButton; public var deleteIcon:FlxSprite; - public function new(property, value, parent) { - super(0, 0, '', function () {}, 280, 35); - members.push(propertyText = new UITextBox(5, 5, property, 100, 25)); - members.push(valueText = new UITextBox(propertyText.x + propertyText.bWidth + 10, 5, value, 135, 25)); + public function new(property, value, parent, width:Int = 280, height:Int = 35, nameWidth:Int = 100, valueWidth:Int = 135, inputHeight:Int = 25) { + super(0, 0, '', function () {}, width, height); + members.push(propertyText = new UITextBox(5, 5, property, nameWidth, inputHeight)); + members.push(valueText = new UITextBox(propertyText.x + propertyText.bWidth + 10, 5, value, valueWidth, inputHeight)); - deleteButton = new UIButton(valueText.x + 135, bHeight/2 - (25/2), "", function () { + var deleteSize = height - 5 * 2; + deleteButton = new UIButton(valueText.x + 135, bHeight/2 - (deleteSize/2), "", function () { parent.remove(this); - }, 25, 25); + }, deleteSize, deleteSize); deleteButton.color = 0xFFFF0000; deleteButton.autoAlpha = false; members.push(deleteButton); - deleteIcon = new FlxSprite(deleteButton.x + (15/2), deleteButton.y + 8).loadGraphic(Paths.image('editors/delete-button')); + deleteIcon = new FlxSprite(deleteButton.x, deleteButton.y).loadGraphic(Paths.image('editors/delete-button')); deleteIcon.antialiasing = false; members.push(deleteIcon); + + updatePos(); } public override function update(elapsed) { super.update(elapsed); - propertyText.follow(this, 5, 5); - valueText.follow(this, propertyText.x + propertyText.bWidth, 5); - deleteButton.follow(this, valueText.x + 135, bHeight/2 - (25/2)); - deleteIcon.follow(deleteButton, 5, 5); + updatePos(); + } + + public function updatePos() { + propertyText.follow(this, 5, bHeight/2 - (propertyText.bHeight/2)); + valueText.follow(this, propertyText.x + propertyText.bWidth, bHeight/2 - (valueText.bHeight/2)); + //deleteButton.follow(this, valueText.x + 135, bHeight/2 - (25/2)); + deleteButton.follow(this, bWidth - deleteButton.bWidth - 5, bHeight/2 - deleteButton.bHeight/2); + deleteIcon.follow(deleteButton, deleteButton.bWidth / 2 - deleteIcon.width / 2, deleteButton.bHeight / 2 - deleteIcon.height / 2); } } \ No newline at end of file diff --git a/source/funkin/editors/stage/StageEditor.hx b/source/funkin/editors/stage/StageEditor.hx index 1ca88bcd..5e926095 100644 --- a/source/funkin/editors/stage/StageEditor.hx +++ b/source/funkin/editors/stage/StageEditor.hx @@ -197,6 +197,7 @@ class StageEditor extends UIState { // Load from xml var order:Array<Dynamic> = []; + var orderNodes:Array<Access> = []; stage = new Stage(__stage, this, false); stage.onXMLLoaded = function(xml:Access, elems:Array<Access>) { return elems; @@ -212,14 +213,14 @@ class StageEditor extends UIState { } stage.onNodeLoaded = function(node:Access, sprite:Dynamic):Dynamic { var parent = new Access(node.x.parent); - var name = ""; + //var name = ""; trace(node, sprite); if(sprite is FlxSprite) { //sprite.forceIsOnScreen = true; // hack } if(sprite is FunkinSprite) { var sprite:FunkinSprite = cast sprite; - name = sprite.name; + //name = sprite.name; sprite.extra.set(exID("node"), node); sprite.extra.set(exID("type"), node.name); sprite.extra.set(exID("imageFile"), '${node.getAtt("sprite").getDefault(sprite.name)}'); @@ -236,7 +237,7 @@ class StageEditor extends UIState { case "girlfriend": "gf"; default: charPos.name; } - name = charPos.name; + //name = charPos.name; var char = new Character(0,0, charName, stage.isCharFlipped(charPos.name, charName == "bf"), true); char.debugMode = true; // Play first anim, and make it the last frame @@ -265,6 +266,7 @@ class StageEditor extends UIState { chars.push(char); } order.push(sprite); + orderNodes.push(node); xmlMap.set(sprite, node); return sprite; @@ -325,7 +327,7 @@ class StageEditor extends UIState { openSubState(substate); } for (i=>sprite in order) { - var xml = xmlMap.get(sprite); + var xml = (sprite != null) ? xmlMap.get(sprite) : orderNodes[i]; if(xml != null) { if(sprite is FunkinSprite) { var sprite:FunkinSprite = cast sprite; @@ -951,7 +953,8 @@ class StageEditor extends UIState { } function handleSelection(sprite:FunkinSprite) { - var buttonBoxes = sprite.extra.get(exID("buttonBoxes")); + if(!sprite.extra.exists(exID("buttonBoxes"))) return; + var buttonBoxes:Array<FlxPoint> = cast sprite.extra.get(exID("buttonBoxes")); dotCheckSize = dot.frameWidth / 0.7/stageCamera.zoom; // basically adjust it to the zoom. diff --git a/source/funkin/editors/stage/elements/StageCharacterButton.hx b/source/funkin/editors/stage/elements/StageCharacterButton.hx index d9660b60..59003bec 100644 --- a/source/funkin/editors/stage/elements/StageCharacterButton.hx +++ b/source/funkin/editors/stage/elements/StageCharacterButton.hx @@ -25,6 +25,8 @@ class StageCharacterButton extends StageElementButton { public override function updateInfo() { char.visible = !isHidden; char.alpha = 0.5 * charPos.alpha; + charPos.scale.x = char.scale.x; + charPos.scale.y = char.scale.y; super.updateInfo(); } diff --git a/source/funkin/editors/ui/UISoftcodedWindow.hx b/source/funkin/editors/ui/UISoftcodedWindow.hx index 7b430bc3..8bf0faca 100644 --- a/source/funkin/editors/ui/UISoftcodedWindow.hx +++ b/source/funkin/editors/ui/UISoftcodedWindow.hx @@ -109,7 +109,8 @@ class UISoftcodedWindow extends UISubstateWindow { set(k, e); } set("self", this); - set("hasSaveButtons", true); + set("hasSaveButton", true); + set("hasCloseButton", true); set("getRadioButtons", function(forID:String) { var radios:Array<UIRadioButton> = cast members.filter((o) -> o is UIRadioButton); return cast radios.filter((o) -> o.forID == forID); @@ -231,6 +232,36 @@ class UISoftcodedWindow extends UISubstateWindow { add(dropdown); addLabelOn(dropdown, label); dropdown; + case "buttonlist": + //x:Float, y:Float, width:Int, height:Int, windowName:String, buttonSize:FlxPoint, ?buttonOffset:FlxPoint, ?buttonSpacing:Float + var buttonlist = new UIButtonList<UIButton>( + x, + y, + execAtt(el, "width"), + execAtt(el, "height"), + execString(el.getAtt("title")).getDefault(""), + FlxPoint.get(execAtt(el, "buttonSizeX", 0), execAtt(el, "buttonSizeY", 0)), + FlxPoint.get(execAtt(el, "buttonOffsetX", 0), execAtt(el, "buttonOffsetY", 0)), + execAtt(el, "buttonSpacing") + ); + var old = get("buttonlist"); + set("buttonlist", buttonlist); + var texture = "editors/ui/inputbox"; + var code = ""; + for(node in getArr(el.elements)) { + switch(node.name) { + case "camSpacing": buttonlist.cameraSpacing = execAtt(node, "value", 0); + case "texture": texture = execString(node.getAtt("path")).getDefault(texture); + case "code": code = node.innerData; + } + } + buttonlist.frames = Paths.getFrames(texture); + if(code != "") + exec(code); + add(buttonlist); + addLabelOn(buttonlist, label); + set("buttonlist", old); + buttonlist; // UIColorwheel // UIAudioPlayer // UIButtonList