Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions assets/data/editors/layouts/stage/animEditScreen.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<window width="660" height="320" title="${translate('win-title', null, [button.animData.name])}">
<set name="MARGIN" value="20" />
<set name="XOFFSET" value="35" />
<set name="YOFFSET" value="40" />
<set name="TO" value="64" />

<exec>
function col(c:Int) {
return MARGIN + (200 + XOFFSET) * c;
}
</exec>

<title name="title" x="MARGIN" y="YOFFSET + 6" text="${translate('anim-title')}"/>

<!-- Alot of terms have already been translated in other places, so they get reused for consistency -->
<section>
<set name="curY" value="title.y + TO"/>
<textbox name="animID" label="${translate('characterAnim.name', 'characterEditor.')}" text="${button.animData.name}" x="col(0)" y="curY" width="120"/>
<stepper name="animFPS" label="${translate('characterAnim.fps', 'characterEditor.')}" value="button.animData.fps" x="last.x + last.bWidth + XOFFSET - 20" y="curY" width="100" precision="2" min="1"/>
<textbox name="animPrefix" label="${translate('characterAnim.anim', 'characterEditor.')}" text="${button.animData.anim}" x="col(1)" y="curY" width="190"/>
<checkbox name="useFrameLabel" value="button.animData.label" x="last.x + last.bWidth + MARGIN" y="curY + 6"/>
<label name="labelText" text="${translate('label')}" x="last.x + last.width + MARGIN - 15" size="15"/>
</section>

<section>
<set name="curY" value="animID.y + animID.bHeight + YOFFSET"/>
<dropdown name="animType" label="${translate('animType', 'stageElementEditScreen.')}" value="button.animData.animType" x="col(0)" y="curY" width="180">
<item label="${translate('animType.none', 'stageElementEditScreen.')}" value="0" />
<item label="${translate('animType.beat', 'stageElementEditScreen.')}" value="1" />
<item label="${translate('animType.loop', 'stageElementEditScreen.')}" value="2" />
</dropdown>
<textbox name="animIndices" label="${translate('characterAnim.indices', 'characterEditor.')}" text="${CoolUtil.formatNumberRange(button.animData.indices, ', ')}" x="col(1)" y="curY" width="200"/>
<stepper name="offsetX" value="button.animData.x" x="col(2)" y="curY" width="100" precision="1"/>
<stepper name="offsetY" value="button.animData.y" x="last.x + last.bWidth + XOFFSET - 20" y="curY" width="100" precision="1"/>
<label name="offsets" text="${translate('offsets')}" x="offsetX.x" y="offsetX.y" size="15"/>
</section>

<section>
<set name="curY" value="self.winHeight - YOFFSET"/>
<checkbox name="loop" text="${translate('characterAnim.looping', 'characterEditor.')}" value="button.animData.loop" x="col(0)" y="curY"/>
<checkbox name="forcedPlay" text="${translate('forcePlay')}" value="CoolUtil.getDefault(button.animData.forced, false)" x="last.x + last.field.width + XOFFSET" y="curY"/>
</section>

<exec>
var prevText:String = animID.label.text;
function onUpdate() {
if (animID.label.text != prevText)
self.winTitle = self.titleSpr.text = translate('win-title', null, [animID.label.text]);
prevText = animID.label.text;

labelText.y = (useFrameLabel.y + (useFrameLabel.height / 2)) - (labelText.height / 2);
}

function onSave() {
button.animData.name = animID.label.text;
button.animData.animType = animType.value;
button.animData.anim = animPrefix.label.text;
button.animData.fps = animFPS.value;
button.animData.x = offsetX.value; button.animData.y = offsetY.value;
button.animData.loop = loop.checked;
button.animData.forced = forcedPlay.checked;
button.animData.indices = CoolUtil.parseNumberRange(animIndices.label.text);
button.animData.label = useFrameLabel.checked;
button.updateDisplay();
}
</exec>
</window>
134 changes: 103 additions & 31 deletions assets/data/editors/layouts/stage/spriteEditScreen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@

<exec>
function col(c:Int) {
return 20 + (200 + XOFFSET) * c;
return MARGIN + (200 + XOFFSET) * c;
}

if(sprite.animateAtlas == null) {
previewSprite = new FunkinSprite(50, self.winHeight - 100);
previewSprite = new FunkinSprite(MARGIN, self.winHeight - (100 + MARGIN));
previewSprite.frame = sprite.frame;

self.add(previewSprite);
}

function animTypeToString(animType:AnimType) {
return ["none", "beat", "loop"][animType];
}
if (getEx('anims') == null)
setEx('anims', sprite.animDatas.copy());
</exec>

<title name="title" x="20" y="30 + 16" text="${translate('sprite-title')}" />
Expand All @@ -25,7 +31,7 @@
<textbox name="nameTextBox" label="${translate('nameID')}" value="button.getName()" x="col(0)" y="curY" width="200" height="32" />
<textbox name="spriteTextBox" value="getEx('imageFile')" x="last.x + last.bWidth + XOFFSET" y="curY" width="200" height="32" />
<stepper name="alphaStepper" label="Alpha" value="sprite.alpha" x="spriteTextBox.x + spriteTextBox.bWidth + XOFFSET" y="curY" precision="2" step="0.01" width="100" />
<label name="imageFile" text="${translate('imageFile')}" x="spriteTextBox.x" y="spriteTextBox.y - 14" size="15" />
<label name="imageFile" text="${translate('imageFile', [stage.spritesParentFolder])}" x="spriteTextBox.x" y="spriteTextBox.y - 14" size="15" />
</section>

<section> <!-- ROW 2 -->
Expand Down Expand Up @@ -64,8 +70,6 @@
<checkbox name="antialiasingCheckbox" text="${translate('antialiasing')}" value="sprite.antialiasing" x="col(0)" y="curY" />
<radio for="memoryCheck" name="highMemoryRadio" text="${translate('highMemory')}" value="getEx('highMemory')" x="col(1)" y="curY" />
<radio for="memoryCheck" name="lowMemoryRadio" text="${translate('lowMemory')}" value="getEx('lowMemory')" x="col(2)" y="curY" />

<!-- TODO: Animation list -->
</section>

<section> <!-- RIGHT SIDE -->
Expand All @@ -77,30 +81,39 @@
<camSpacing value="0" />

<code>
buttonlist.addButton.exists = false;
</code>

<!-- <code>
import funkin.editors.extra.PropertyButton;
//import funkin.backend.utils.XMLUtil.AnimData;
import funkin.editors.stage.elements.StageSpriteAnimButton;

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;

inline function addAnimBtn(animData:AnimData) {
var animButton = new StageSpriteAnimButton(animData, buttonList, width, height, width / 5, width / 3);
animButton.spriteXML = xml;
buttonList.add(animButton);
}

buttonList.addButton.callback = function() {
buttonList.add(new PropertyButton("newProperty", "valueHere", buttonList, width, height, 150, 220, 25));
final dummyAnim = {
name: TranslationUtil.translate('characterEditor.characterAnim.defaultAnimName'),
anim: translate('defaultAnimPrefix'),
fps: 24,
loop: false,
animType: animType.value,
x: 0,
y: 0,
indices: [],
label: false
};
addAnimBtn(dummyAnim);
}

//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 =&gt; val in stage.extra)
buttonList.add(new PropertyButton(key, val, buttonList, width, height, 150, 220, 25));
</code> -->
for (animData in getEx('anims')) {
if (animData.name == 'idle' &amp;&amp; animData.anim == null) continue; // Skips dummy animation added by XMLUtil.loadSpriteFromXML
addAnimBtn(animData);
}
</code>
</buttonlist>

<text text="${translate('tipCustomProperties')}" x="col(2) - 60" y="self.winHeight - 50" size="15" />
Expand All @@ -111,35 +124,61 @@

<section if="previewSprite != null">
<title name="previewTitle" x="20" y="self.winHeight - 150" text="${translate('transformPreview')}" size="15" />
</section>
</section>

<exec>
var prevText = spriteTextBox.label.text;
var prevID = nameTextBox.label.text;
var spriteExists = true;
var ratio = sprite.width / sprite.height;

spriteTextBox.onChange = function(text) {
var newSprite = stage.spritesParentFolder + text;
var animated = Paths.framesExists(newSprite, true);
spriteExists = ( animated || Assets.exists(Paths.image(newSprite)) );

if (text != prevText &amp;&amp; spriteExists) {
if (animated) previewSprite.frames = Paths.getFrames(newSprite, previewSprite.animateSettings);
else previewSprite.loadGraphic(Paths.image(newSprite));
previewSprite.updateHitbox();

ratio = previewSprite.width / previewSprite.height;
previewSprite.colorTransform.__identity();
} else if (!spriteExists) {
previewSprite.colorTransform.color = 0xFFEF0202;
}
prevText = text;
}

function onUpdate() {
if (nameTextBox.label.text != prevID)
self.winTitle = self.titleSpr.text = translate('win-sprite-title', [nameTextBox.label.text]);
prevID = nameTextBox.label.text;

if(previewSprite == null) return;
previewSprite.color = 0xFFFFFFFF; // TODO: Color Wheel
previewSprite.skew.x = skewXStepper.value;
previewSprite.skew.y = skewYStepper.value;
previewSprite.angle = angleStepper.value;
previewSprite.alpha = alphaStepper.value;
previewSprite.antialiasing = antialiasingCheckbox.checked;
var ratio = sprite.width / sprite.height;
previewSprite.setGraphicSize(50 * scaleXStepper.value * ratio, 50 * scaleYStepper.value);
previewSprite.setGraphicSize(85 * scaleXStepper.value * ratio, 85 * scaleYStepper.value);
previewSprite.updateHitbox();
}

function onSave() {
sprite.name = nameTextBox.label.text;
setEx("imageFile", spriteTextBox.label.text);

setEx("highMemory", highMemoryRadio.checked);
setEx("lowMemory", lowMemoryRadio.checked);

//sprite.x = xStepper.value;
//sprite.y = yStepper.value;
//sprite.zoomFactor = zoomFactorStepper.value;
//sprite.antialiasing = antialiasingCheckbox.checked;
sprite.x = xStepper.value;
sprite.y = yStepper.value;
sprite.zoomFactor = zoomFactorStepper.value;
sprite.antialiasing = antialiasingCheckbox.checked;
//sprite.color = colorWheel.color;
//sprite.spriteAnimType = animType.value;
sprite.spriteAnimType = animTypeToString(animType.value);
sprite.angle = angleStepper.value;
sprite.alpha = alphaStepper.value;

Expand Down Expand Up @@ -171,15 +210,48 @@
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("type", animTypeToString(animType.value));
button.xml.set("antialiasing", antialiasingCheckbox.checked);
button.xml.set("angle", angleStepper.value);
button.xml.set("alpha", alphaStepper.value);

getEx('anims').clear();
var allowedAnims:Array&lt;String&gt; = [for (b in animations.buttons.members) b.animData.name];
for (node in button.xml.elementsNamed('anim')) if (!allowedAnims.contains( node.get('name') ))
button.xml.removeChild(node);

for (i in 0...animations.buttons.length) {
var actualChildren:Array&lt;Xml&gt; = button.xml.children.filter((f) -&gt; f.nodeType == 0);
if (i &gt; actualChildren.length - 1) {
var newAnim = Xml.createElement('anim');
button.xml.addChild(newAnim);
actualChildren.push(newAnim);
//trace("added new at " + i + ": " + newAnim);
}

final animData:AnimData = animations.buttons.members[i].animData;
final animNode:Xml = actualChildren[i];
//trace(animNode + "(" + i + ") before");
animNode.set("name", animData.name);
animNode.set("type", animTypeToString(animData.animType)); // XMLAnimType is abstract of int, the code is treating it as just int
animNode.set("anim", animData.anim);
animNode.set("fps", animData.fps);
animNode.set("x", animData.x);
animNode.set("y", animData.y);
animNode.set("loop", animData.loop);
animNode.set("forced", CoolUtil.getDefault(animData.forced, false));
animNode.set("indices", CoolUtil.formatNumberRange(animData.indices));
animNode.set("label", animData.label);
//trace(animNode + "(" + i + ")");
getEx('anims').set(animData.name, animData);
}

saveXY(sprite.scrollFactor, "scroll", scrollXStepper, scrollYStepper);
saveXY(sprite.scale, "scale", scaleXStepper, scaleYStepper);
saveXY(sprite.skew, "skew", skewXStepper, skewYStepper);
XMLUtil.loadSpriteFromXML(sprite, button.xml, stage.spritesParentFolder);
button.updateInfo();
setEx('node', button.xml);
}
</exec>
</window>
17 changes: 15 additions & 2 deletions assets/languages/en/Editors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -592,8 +592,9 @@
<str id="title">Stage Info</str>
<str id="stageName">Stage Name</str>
<str id="spritePath">Sprite Path\n(Needs Refresh)</str>
<str id="startCamPos">Start Camera Position (X, Y)</str>
<str id="startCamPos">Start Camera Position\n(X, Y)</str>
<str id="zoom">Zoom</str>
<str id="customAttributes">Custom Attributes</str>
</group>

<group name="StageElementEditScreen" prefix="stageElementEditScreen.">
Expand All @@ -607,7 +608,7 @@

<str id="elementName">Element Name</str>
<str id="nameID">Name Identifier</str>
<str id="imageFile">Image File (WIP: needs reload)\nIn (${stage.spritesParentFolder})</str>
<str id="imageFile">Image File\n(in "{0}")</str>
<str id="scroll">Scroll {0}</str>
<str id="scale">Scale {0}</str>
<str id="camera">Camera {0}</str>
Expand All @@ -623,6 +624,7 @@
<str id="lowMemory">Low Memory</str>
<str id="attributes">Attributes</str>
<str id="transformPreview">Transform Preview:</str>
<str id="animations">Animations</str>

<str id="animType">Animation Type</str>
<group name="AnimTypeDropdown" prefix="animType.">
Expand All @@ -631,6 +633,8 @@
<str id="loop">LOOP</str>
</group>
<str id="tipCustomProperties">Tip: To access custom properties,\nHold Shift when clicking edit</str>

<str id="defaultAnimPrefix">Name on Anim Data</str>
</group>

<group name="StageXMLEditScreen" prefix="stageXMLEditScreen.">
Expand All @@ -645,6 +649,7 @@
<group name="StageElement" prefix="stageElement.">
<str id="scale">Scale: {0}, {1}</str>
<str id="scroll">Scroll: {0}, {1}</str>
<str id="unknown">Unknown Sprite:\n{0}</str>
</group>

<group name="StageSprites" prefix="stageSprites.">
Expand All @@ -654,6 +659,14 @@
<str id="character">Character</str>
<str id="warnings.not-implemented">Creating a box isnt implemented yet!</str>
</group>

<group name="StageAnimEdit" prefix="stageSpriteAnimEditScreen.">
<str id="win-title">Editing "{0}" Anim</str>
<str id="anim-title">Anim Data</str>
<str id="label">Use Frame Labels?</str>
<str id="offsets">Offset (X, Y)</str>
<str id="forcePlay">Forced Playing?</str>
</group>
</group>

<!-- PlayTesting and SaveWarning are almost the same but with some small differences -->
Expand Down
6 changes: 4 additions & 2 deletions assets/languages/es/Editors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@
<str id="title">Info. del Escenario</str>
<str id="stageName">Nombre del Escenario</str>
<str id="spritePath">Ubicación de Imágenes\n(Necesita Refrescar)</str>
<str id="startCamPos">Posición inicial de la cámara (X, Y)</str>
<str id="startCamPos">Posición inicial de la cámara\n(X, Y)</str>
<str id="zoom">Zoom</str>
</group>

Expand All @@ -566,7 +566,7 @@

<str id="elementName">Nombre del Elemento</str>
<str id="nameID">Identificador de Nombre</str>
<str id="imageFile">Imagen (WIP: necesita refrescar)\nEn (${stage.spritesParentFolder})</str>
<str id="imageFile">Imagen\n(en "{0}")</str>
<str id="scroll">Desplazamiento {0}</str>
<str id="scale">Tamaño {0}</str>
<str id="camera">Cámara {0}</str>
Expand All @@ -580,6 +580,7 @@
<str id="lowMemory">Baja Memoria</str>
<str id="attributes">Atributos</str>
<str id="transformPreview">Preview:</str>
<str id="animations">Animaciónes</str>

<str id="animType">Tipo de Animación</str>
<group name="AnimTypeDropdown" prefix="animType.">
Expand All @@ -602,6 +603,7 @@
<group name="StageElement" prefix="stageElement.">
<str id="scale">Tamaño: {0}, {1}</str>
<str id="scroll">Desplazamiento: {0}, {1}</str>
<str id="unknown">Sprite Desconocido:\n{0}</str>
</group>

<group name="StageSprites" prefix="stageSprites.">
Expand Down
Loading