Added preview + cleaner dropdown xml

This commit is contained in:
NeeEoo
2024-04-14 17:38:00 +02:00
parent 1763b09a7b
commit b537ca2b95
5 changed files with 154 additions and 46 deletions
@@ -1,42 +1,79 @@
<window width="1056" height="520" title="Editing Sprite">
<set name="XOFFSET" value="40" />
<set name="XOFFSET" value="50" />
<set name="YOFFSET" value="40" />
<set name="TO" value="64" />
<title name="title" x="20" y="30 + 16" label="Sprite Data" />
<exec>
previewSprite = new FunkinSprite(50, self.winHeight - 100);
previewSprite.frame = sprite.frame;
<textbox name="nameTextBox" label="Name Identifier" text="${data.getName()}" x="20" y="title.y + TO" width="200" height="32" />
<textbox name="spriteTextBox" label="Image File (${stage.spritesParentFolder})" text="${getEx('imageFile')}" x="last.x + last.bWidth + XOFFSET" y="title.y + TO" width="200" height="32" />
self.add(previewSprite);
</exec>
<set name="curY" value="nameTextBox.y + nameTextBox.bHeight + YOFFSET" />
<title name="title" x="20" y="30 + 16" text="Sprite Data" />
<set name="curY" value="title.y + TO" /> <!-- ROW 1 -->
<textbox name="nameTextBox" label="Name Identifier" text="${data.getName()}" x="20" y="curY" width="200" height="32" />
<textbox name="spriteTextBox" label="Image File (${stage.spritesParentFolder})" text="${getEx('imageFile')}" x="last.x + last.bWidth + XOFFSET" y="curY" width="200" height="32" />
<set name="curY" value="nameTextBox.y + nameTextBox.bHeight + YOFFSET" /> <!-- ROW 2 -->
<stepper name="xStepper" label="X" value="sprite.x" x="20" 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" step="0.01" width="100" />
<stepper name="scrollYStepper" label="Scroll Y" value="sprite.scrollFactor.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" 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="20 + (200 + XOFFSET) * 2" y="curY" step="0.01" width="100" />
<stepper name="scaleYStepper" label="Scale Y" value="sprite.scale.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" step="0.01" width="100" />
<stepper name="scaleXStepper" label="Scale X" value="sprite.scale.x" x="20 + (200 + XOFFSET) * 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="skewXStepper" label="Skew X" value="sprite.skew.x" x="20 + (200 + XOFFSET) * 3" y="curY" step="0.01" width="100" />
<stepper name="skewYStepper" label="Skew Y" value="sprite.skew.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" step="0.01" width="100" />
<set name="curY" value="xStepper.y + xStepper.bHeight + YOFFSET" /> <!-- ROW 3 -->
<set name="curY" value="xStepper.y + xStepper.bHeight + YOFFSET" />
<stepper name="angleStepper" label="Angle" value="sprite.angle" x="20 + (200 + XOFFSET) * 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="20 + (200 + XOFFSET) * 0" y="curY" step="0.01" width="100" />
<stepper name="zoomFactorStepper" label="Zoom Factor" value="sprite.zoomFactor" x="20 + (200 + XOFFSET) * 1" y="curY" step="0.01" width="100" />
<stepper name="skewXStepper" label="Skew X" value="sprite.skew.x" x="20 + (200 + XOFFSET) * 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" />
<dropdown name="animType" label="Animation Type" value="['NONE','BEAT','LOOP'][sprite.spriteAnimType]" x="20 + (200 + XOFFSET) * 2" y="curY" width="100" height="32" options="NONE,BEAT,LOOP" />
<!-- TODO: Simplify this -->
<dropdown name="animType" label="Animation Type" value="sprite.spriteAnimType" x="20 + (200 + XOFFSET) * 1" y="curY" width="150" height="32">
<item label="NONE" value="0" />
<item label="BEAT" value="1" />
<item label="LOOP" value="2" />
</dropdown>
<!-- ROW 4 -->
<set name="curY" value="angleStepper.y + angleStepper.bHeight + YOFFSET" />
<checkbox name="antialiasingCheckbox" text="Antialiasing" value="sprite.antialiasing" x="20 + (200 + XOFFSET) * 0" y="curY" />
<!-- TODO: Animation list -->
<!-- Preview Transform -->
<title name="previewTitle" x="20" y="self.winHeight - 150" text="Preview Transform:" size="14" />
<exec>
function onUpdate() {
previewSprite.color = 0xFFFFFFFF;
previewSprite.skew.x = skewXStepper.value;
previewSprite.skew.y = skewYStepper.value;
previewSprite.angle = angleStepper.value;
var ratio = sprite.width / sprite.height;
previewSprite.setGraphicSize(50 * scaleXStepper.value * ratio, 50 * scaleYStepper.value);
previewSprite.updateHitbox();
}
function onSave() {
sprite.x = xStepper.value;
sprite.y = yStepper.value;
sprite.zoomFactor = zoomFactorStepper.value;
//sprite.antialiasing = antialiasingCheckbox.checked;
sprite.antialiasing = antialiasingCheckbox.checked;
//sprite.color = colorWheel.color;
sprite.spriteAnimType = animType.index;
sprite.spriteAnimType = animType.value;
sprite.angle = angleStepper.value;
function saveXY(obj:Dynamic, name:String, x:UINumericStepper, y:UINumericStepper) {
data.xml.remove(name + "");
@@ -57,7 +94,9 @@
data.xml.set("x", xStepper.value);
data.xml.set("y", yStepper.value);
data.xml.set("zoom", zoomFactorStepper.value);
data.xml.set("type", ['NONE','BEAT','LOOP'][animType.index]);
data.xml.set("type", animType.key);
data.xml.set("antialiasing", antialiasingCheckbox.checked);
data.xml.set("angle", angleStepper.value);
saveXY(sprite.scrollFactor, "scroll", scrollXStepper, scrollYStepper);
saveXY(sprite.scale, "scale", scaleXStepper, scaleYStepper);
+9
View File
@@ -29,6 +29,15 @@ enum abstract XMLAnimType(Int)
default: def;
}
}
@:to public function toString():String {
return switch (cast this)
{
case NONE: "none";
case BEAT: "beat";
case LOOP: "loop";
}
}
}
class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements IOffsetCompatible implements IXMLEvents
+1 -1
View File
@@ -561,7 +561,7 @@ class StageEditor extends UIState {
FlxPoint.get(0.5, 0),
// center
//FlxPoint.get(0.5, 0.5)
], sprite.camera, sprite.width, sprite.height);
], sprite.camera, sprite.frameWidth, sprite.frameHeight);
//Logs.trace("Guide at " + corners[0].x + ", " + corners[0].y + " sprite at " + sprite.x + ", " + sprite.y);
@@ -1,14 +1,16 @@
package funkin.editors.stage;
import funkin.backend.scripting.HScript;
import hscript.Interp;
import haxe.xml.Access;
import flixel.math.FlxPoint;
import funkin.backend.chart.ChartData.ChartMetaData;
import funkin.backend.scripting.HScript;
import funkin.backend.scripting.Script;
import funkin.editors.extra.PropertyButton;
import funkin.editors.stage.elements.StageElementButton;
import funkin.editors.ui.UIDropDown;
import haxe.xml.Access;
import hscript.*;
import hscript.Expr.Error;
import hscript.Interp;
import hscript.Parser;
using StringTools;
@@ -47,7 +49,11 @@ class StageSpriteEditScreen extends UISubstateWindow {
sprite = data.getSprite();
for(k=>e in Script.getDefaultVariables()) {
set(k, e);
}
set("stage", StageEditor.instance.stage);
set("self", this);
set("sprite", sprite);
set("data", data);
set("getEx", function(name:String):Dynamic {
@@ -84,24 +90,24 @@ class StageSpriteEditScreen extends UISubstateWindow {
function addLabelOn(ui:UISprite, text:String)
add(new UIText(ui.x, ui.y - 24, 0, text));
function execString(code:String):String {
if(code.indexOf("${") == -1) return code;
function execString(input:String):String {
if(input.indexOf("${") == -1) return input;
var text = "";
while(code.length > 0) {
var idx = code.indexOf("${");
while(input.length > 0) {
var idx = input.indexOf("${");
if(idx == -1) {
text += code;
text += input;
break;
}
text += code.substring(0, idx);
var ei = code.indexOf("}", idx);
text += input.substring(0, idx);
var ei = input.indexOf("}", idx);
if(ei == -1) {
text += code.substring(idx);
text += input.substring(idx);
break;
}
var block = code.substring(idx+2, ei);
var block = input.substring(idx+2, ei);
text += exec(block);
code = code.substring(ei + 1);
input = input.substring(ei + 1);
}
return text;
}
@@ -117,7 +123,7 @@ class StageSpriteEditScreen extends UISubstateWindow {
for(el in layout.elements) {
var type = el.name;
//var type:String = el.getAtt("type");
var name:String = el.getAtt("name");
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);
@@ -130,21 +136,28 @@ class StageSpriteEditScreen extends UISubstateWindow {
var sprite:FlxSprite = switch(type) {
case "set":
set(el.getAtt("name"), exec(el.getAtt("value")));
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, (el.getAtt("multiline").getDefault("false") == "true"));
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, label, size));
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(
@@ -162,7 +175,7 @@ class StageSpriteEditScreen extends UISubstateWindow {
addLabelOn(stepper, label);
stepper;
case "checkbox":
var checkbox = new UICheckbox(x, y, label, execAtt(el, "value", false));
var checkbox = new UICheckbox(x, y, text, execAtt(el, "value", false));
add(checkbox);
addLabelOn(checkbox, label);
checkbox;
@@ -172,11 +185,14 @@ class StageSpriteEditScreen extends UISubstateWindow {
addLabelOn(slider, label);
slider;
case "dropdown":
var options = execString(el.getAtt("options")).split(",");
var items:Array<DropDownItem> = [];
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 = options.indexOf(curValue);
var index = UIDropDown.indexOfItemValue(items, curValue);
if (index == -1) index = 0;
var dropdown = new UIDropDown(x, y, width, height, options, index);
var dropdown = new UIDropDown(x, y, width, height, items, index);
add(dropdown);
addLabelOn(dropdown, label);
dropdown;
@@ -248,6 +264,11 @@ class StageSpriteEditScreen extends UISubstateWindow {
return null;
}
override function update(elapsed:Float) {
super.update(elapsed);
callFunc("onUpdate", [elapsed]);
}
public function saveData() {
for (el in elementMap) {
if(el is UINumericStepper) {
+45 -6
View File
@@ -1,34 +1,68 @@
package funkin.editors.ui;
import flixel.util.typeLimit.OneOfTwo;
class UIDropDown extends UISliceSprite {
public var dropButton:UIButton;
public var label:UIText;
public var index:Int = 0;
public var options:Array<String>;
public var items:Array<DropDownItem>;
public var key(get, never):String;
inline function get_key():String {
return items[index].label;
}
public var value(get, never):Dynamic;
inline function get_value():Dynamic {
return items[index].value;
}
public var onChange:Int->Void;
var curMenu:UIContextMenu = null;
public function new(x:Float, y:Float, width:Int = 320, height:Int = 32, options:Array<String>, index:Int = 0) {
public static function getItems(options:Array<String>):Array<DropDownItem> {
return [for(i=>o in options) {label: o, value: i}];
}
public function new(x:Float, y:Float, width:Int = 320, height:Int = 32, _options:Array<OneOfTwo<DropDownItem, String>>, index:Int = 0) {
super(x, y, width - height, height, 'editors/ui/inputbox'); // using same sprite cause fuck you
this.options = options;
var _items:Array<DropDownItem> = [];
if(_options.length > 0) {
if(_options[0] is String) {
_items = getItems(_options);
} else {
_items = cast _options;
}
}
this.items = _items;
this.options = [for(o in _items) o.label]; // backwards compatibility
this.index = index;
cursor = BUTTON;
label = new UIText(0, 0, width - height, options[index]);
label = new UIText(0, 0, width - height, items[index].label);
members.push(label);
dropButton = new UIButton(0, 0, "V", null, height, height);
members.push(dropButton);
}
public static function indexOfItemValue(items:Array<DropDownItem>, value:Dynamic):Int {
return [for(o in items) o.value].indexOf(value);
}
public static function indexOfItemLabel(items:Array<DropDownItem>, str:String):Int {
return [for(o in items) o.label].indexOf(str);
}
public function setOption(newIndex:Int) {
if (index != (index = newIndex)) {
label.text = options[index];
label.text = items[index].label;
if (onChange != null)
onChange(index);
}
@@ -53,12 +87,17 @@ class UIDropDown extends UISliceSprite {
public function openContextMenu() {
var screenPos = getScreenPosition(null, __lastDrawCameras[0] == null ? FlxG.camera : __lastDrawCameras[0]);
curMenu = UIState.state.openContextMenu([
for(k=>o in options) {
for(k=>o in items) {
icon: (k == index) ? 1 : 0,
label: o
label: o.label
}
], function(_, i, _) {
setOption(i);
}, __lastDrawCameras[0].x + screenPos.x, __lastDrawCameras[0].y + screenPos.y + bHeight);
}
}
typedef DropDownItem = {
var label:String;
var value:Dynamic;
}