66
77 <exec >
88 function col(c:Int) {
9- return 20 + (200 + XOFFSET) * c;
9+ return MARGIN + (200 + XOFFSET) * c;
1010 }
1111
1212 if(sprite.animateAtlas == null) {
13- previewSprite = new FunkinSprite(50 , self.winHeight - 100);
13+ previewSprite = new FunkinSprite(MARGIN , self.winHeight - ( 100 + MARGIN) );
1414 previewSprite.frame = sprite.frame;
1515
1616 self.add(previewSprite);
1717 }
18+
19+ function animTypeToString(animType:AnimType) {
20+ return ["none", "beat", "loop"][animType];
21+ }
22+ if (getEx('anims') == null)
23+ setEx('anims', sprite.animDatas.copy());
1824 </exec >
1925
2026 <title name =" title" x =" 20" y =" 30 + 16" text =" ${translate('sprite-title')}" />
2531 <textbox name =" nameTextBox" label =" ${translate('nameID')}" value =" button.getName()" x =" col(0)" y =" curY" width =" 200" height =" 32" />
2632 <textbox name =" spriteTextBox" value =" getEx('imageFile')" x =" last.x + last.bWidth + XOFFSET" y =" curY" width =" 200" height =" 32" />
2733 <stepper name =" alphaStepper" label =" Alpha" value =" sprite.alpha" x =" spriteTextBox.x + spriteTextBox.bWidth + XOFFSET" y =" curY" precision =" 2" step =" 0.01" width =" 100" />
28- <label name =" imageFile" text =" ${translate('imageFile')}" x =" spriteTextBox.x" y =" spriteTextBox.y - 14" size =" 15" />
34+ <label name =" imageFile" text =" ${translate('imageFile', [stage.spritesParentFolder] )}" x =" spriteTextBox.x" y =" spriteTextBox.y - 14" size =" 15" />
2935 </section >
3036
3137 <section > <!-- ROW 2 -->
6470 <checkbox name =" antialiasingCheckbox" text =" ${translate('antialiasing')}" value =" sprite.antialiasing" x =" col(0)" y =" curY" />
6571 <radio for =" memoryCheck" name =" highMemoryRadio" text =" ${translate('highMemory')}" value =" getEx('highMemory')" x =" col(1)" y =" curY" />
6672 <radio for =" memoryCheck" name =" lowMemoryRadio" text =" ${translate('lowMemory')}" value =" getEx('lowMemory')" x =" col(2)" y =" curY" />
67-
68- <!-- TODO: Animation list -->
6973 </section >
7074
7175 <section > <!-- RIGHT SIDE -->
7781 <camSpacing value =" 0" />
7882
7983 <code >
80- buttonlist.addButton.exists = false;
81- </code >
82-
83- <!-- <code>
84- import funkin.editors.extra.PropertyButton;
84+ //import funkin.backend.utils.XMLUtil.AnimData;
85+ import funkin.editors.stage.elements.StageSpriteAnimButton;
8586
8687 var buttonList = buttonlist; // important for now, since it gets reset after the code is run
87-
8888 var width = buttonList.buttonSize.x;
8989 var height = buttonList.buttonSize.y;
9090
91+ inline function addAnimBtn(animData:AnimData) {
92+ var animButton = new StageSpriteAnimButton(animData, buttonList, width, height, width / 5, width / 3);
93+ animButton.spriteXML = xml;
94+ buttonList.add(animButton);
95+ }
96+
9197 buttonList.addButton.callback = function() {
92- buttonList.add(new PropertyButton("newProperty", "valueHere", buttonList, width, height, 150, 220, 25));
98+ final dummyAnim = {
99+ name: TranslationUtil.translate('characterEditor.characterAnim.defaultAnimName'),
100+ anim: translate('defaultAnimPrefix'),
101+ fps: 24,
102+ loop: false,
103+ animType: animType.value,
104+ x: 0,
105+ y: 0,
106+ indices: [],
107+ label: false
108+ };
109+ addAnimBtn(dummyAnim);
93110 }
94111
95- //var defaultAttribs = Stage.DEFAULT_ATTRIBUTES;
96- //for (i in stage.stageXML.attributes()) {
97- // trace(i, defaultAttribs);
98- // if (!defaultAttribs.contains(i))
99- // buttonList.add(new PropertyButton(i, stage.stageXML.get(i), buttonList, width, height, 150, 220, 25));
100- //}
101- for(key => val in stage.extra)
102- buttonList.add(new PropertyButton(key, val, buttonList, width, height, 150, 220, 25));
103- </code> -->
112+ for (animData in getEx('anims')) {
113+ if (animData.name == 'idle' && animData.anim == null) continue; // Skips dummy animation added by XMLUtil.loadSpriteFromXML
114+ addAnimBtn(animData);
115+ }
116+ </code >
104117 </buttonlist >
105118
106119 <text text =" ${translate('tipCustomProperties')}" x =" col(2) - 60" y =" self.winHeight - 50" size =" 15" />
111124
112125 <section if =" previewSprite != null" >
113126 <title name =" previewTitle" x =" 20" y =" self.winHeight - 150" text =" ${translate('transformPreview')}" size =" 15" />
114- </section >
127+ </section >
115128
116129 <exec >
130+ var prevText = spriteTextBox.label.text;
131+ var prevID = nameTextBox.label.text;
132+ var spriteExists = true;
133+ var ratio = sprite.width / sprite.height;
134+
135+ spriteTextBox.onChange = function(text) {
136+ var newSprite = stage.spritesParentFolder + text;
137+ var animated = Paths.framesExists(newSprite, true);
138+ spriteExists = ( animated || Assets.exists(Paths.image(newSprite)) );
139+
140+ if (text != prevText && spriteExists) {
141+ if (animated) previewSprite.frames = Paths.getFrames(newSprite, previewSprite.animateSettings);
142+ else previewSprite.loadGraphic(Paths.image(newSprite));
143+ previewSprite.updateHitbox();
144+
145+ ratio = previewSprite.width / previewSprite.height;
146+ previewSprite.colorTransform.__identity();
147+ } else if (!spriteExists) {
148+ previewSprite.colorTransform.color = 0xFFEF0202;
149+ }
150+ prevText = text;
151+ }
152+
117153 function onUpdate() {
154+ if (nameTextBox.label.text != prevID)
155+ self.winTitle = self.titleSpr.text = translate('win-sprite-title', [nameTextBox.label.text]);
156+ prevID = nameTextBox.label.text;
157+
118158 if(previewSprite == null) return;
119159 previewSprite.color = 0xFFFFFFFF; // TODO: Color Wheel
120160 previewSprite.skew.x = skewXStepper.value;
121161 previewSprite.skew.y = skewYStepper.value;
122162 previewSprite.angle = angleStepper.value;
123163 previewSprite.alpha = alphaStepper.value;
124164 previewSprite.antialiasing = antialiasingCheckbox.checked;
125- var ratio = sprite.width / sprite.height;
126- previewSprite.setGraphicSize(50 * scaleXStepper.value * ratio, 50 * scaleYStepper.value);
165+ previewSprite.setGraphicSize(85 * scaleXStepper.value * ratio, 85 * scaleYStepper.value);
127166 previewSprite.updateHitbox();
128167 }
129-
168+
130169 function onSave() {
131170 sprite.name = nameTextBox.label.text;
132171 setEx("imageFile", spriteTextBox.label.text);
133172
134173 setEx("highMemory", highMemoryRadio.checked);
135174 setEx("lowMemory", lowMemoryRadio.checked);
136175
137- // sprite.x = xStepper.value;
138- // sprite.y = yStepper.value;
139- // sprite.zoomFactor = zoomFactorStepper.value;
140- // sprite.antialiasing = antialiasingCheckbox.checked;
176+ sprite.x = xStepper.value;
177+ sprite.y = yStepper.value;
178+ sprite.zoomFactor = zoomFactorStepper.value;
179+ sprite.antialiasing = antialiasingCheckbox.checked;
141180 //sprite.color = colorWheel.color;
142- // sprite.spriteAnimType = animType.value;
181+ sprite.spriteAnimType = animTypeToString( animType.value) ;
143182 sprite.angle = angleStepper.value;
144183 sprite.alpha = alphaStepper.value;
145184
171210 button.xml.set("x", xStepper.value);
172211 button.xml.set("y", yStepper.value);
173212 button.xml.set("zoom", zoomFactorStepper.value);
174- button.xml.set("type", animType.key );
213+ button.xml.set("type", animTypeToString( animType.value) );
175214 button.xml.set("antialiasing", antialiasingCheckbox.checked);
176215 button.xml.set("angle", angleStepper.value);
177216 button.xml.set("alpha", alphaStepper.value);
178217
218+ getEx('anims').clear();
219+ var allowedAnims:Array< String> = [for (b in animations.buttons.members) b.animData.name];
220+ for (node in button.xml.elementsNamed('anim')) if (!allowedAnims.contains( node.get('name') ))
221+ button.xml.removeChild(node);
222+
223+ for (i in 0...animations.buttons.length) {
224+ var actualChildren:Array< Xml> = button.xml.children.filter((f) -> f.nodeType == 0);
225+ if (i > actualChildren.length - 1) {
226+ var newAnim = Xml.createElement('anim');
227+ button.xml.addChild(newAnim);
228+ actualChildren.push(newAnim);
229+ //trace("added new at " + i + ": " + newAnim);
230+ }
231+
232+ final animData:AnimData = animations.buttons.members[i].animData;
233+ final animNode:Xml = actualChildren[i];
234+ //trace(animNode + "(" + i + ") before");
235+ animNode.set("name", animData.name);
236+ animNode.set("type", animTypeToString(animData.animType)); // XMLAnimType is abstract of int, the code is treating it as just int
237+ animNode.set("anim", animData.anim);
238+ animNode.set("fps", animData.fps);
239+ animNode.set("x", animData.x);
240+ animNode.set("y", animData.y);
241+ animNode.set("loop", animData.loop);
242+ animNode.set("forced", CoolUtil.getDefault(animData.forced, false));
243+ animNode.set("indices", CoolUtil.formatNumberRange(animData.indices));
244+ animNode.set("label", animData.label);
245+ //trace(animNode + "(" + i + ")");
246+ getEx('anims').set(animData.name, animData);
247+ }
248+
179249 saveXY(sprite.scrollFactor, "scroll", scrollXStepper, scrollYStepper);
180250 saveXY(sprite.scale, "scale", scaleXStepper, scaleYStepper);
181251 saveXY(sprite.skew, "skew", skewXStepper, skewYStepper);
182252 XMLUtil.loadSpriteFromXML(sprite, button.xml, stage.spritesParentFolder);
253+ button.updateInfo();
254+ setEx('node', button.xml);
183255 }
184256 </exec >
185257</window >
0 commit comments