Skip to content

Commit a9fd286

Browse files
committed
re
1 parent f10d664 commit a9fd286

File tree

7 files changed

+453
-151
lines changed

7 files changed

+453
-151
lines changed

data/config/credits.xml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
<!DOCTYPE codename-mod-credits>
22
<!-- TEMPLATE FOR CUSTOM CREDITS!!! -->
3-
<<<<<<< HEAD
43
<menu name="Secret of Rerun Credits" desc="Credits for Secret of Rerun Credits.">
54
<credit portrait="false" name="Nikita_Sergay" desc="But it all started with a joke...
65
Owner Secret of Rerun, Artist and Charter" icon="omg" size="150" url="https://gamebanana.com/members/3506058"/>
76
<credit portrait="false" name="NikkiRemo" desc="TwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwisted
87
Main coder and tracer" icon="NikkiRemo" size="180" url="https://www.youtube.com/@Ant1C0de"/>
98
<credit portrait="false" name="Yururyu" desc="I'm just here for fun
109
Traced logo anim" icon="sona" size="180" url="https://t.me/notnamspublic"/>
11-
=======
12-
<menu name="Secret of Rerun Cretits" desc="Credits for Secret of Rerun Cretits.">
13-
<credit portrait="ftruealse" name="NikkiRemo" desc="TwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwistedTwisted
14-
Main coder and tracer" icon="NikkiRemo" size="140" url="https://www.youtube.com/@Ant1C0de"/>
15-
>>>>>>> parent of 64fd1f3 (чистка ассетов для альфы)
1610
<credit portrait="true" name="nova" desc="hi im nova teheehehe
1711
nothing special (code etc.)" icon="nova" size="110" url="https://github.com/novathepurplecord"/>
1812
<credit portrait="true" name="Andrewbit" desc="pisya popa chle-
Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
import funkin.backend.assets.ModsFolder;
2+
import funkin.backend.utils.XMLUtil;
3+
import funkin.backend.utils.CoolUtil;
4+
import funkin.editors.character.CharacterAnimScreen;
5+
import funkin.editors.ui.UIState;
6+
import funkin.editors.ui.UIText;
7+
import funkin.editors.ui.UIButton;
8+
import funkin.editors.ui.UITextBox;
9+
import funkin.editors.ui.UINumericStepper;
10+
import funkin.editors.ui.UICheckbox;
11+
import funkin.editors.ui.UIColorwheel;
12+
import funkin.editors.ui.UIButtonList;
13+
import funkin.editors.ui.UIWarningSubstate;
14+
import funkin.game.Character;
15+
16+
import haxe.xml.Printer;
17+
import haxe.io.Path;
18+
19+
import lime.ui.FileDialog;
20+
import lime.ui.FileDialogType;
21+
22+
import openfl.utils.Assets;
23+
24+
import sys.io.File;
25+
import sys.FileSystem;
26+
27+
import CharacterAnimInfoButton; //Custom class
28+
29+
import Xml;
30+
import Std;
31+
32+
public var spriteTextBox:UITextBox;
33+
public var iconTextBox:UITextBox;
34+
public var iconSprite:FlxSprite;
35+
public var gameOverCharTextBox:UITextBox;
36+
public var antialiasingCheckbox:UICheckbox;
37+
public var flipXCheckbox:UICheckbox;
38+
public var iconColorWheel:UIColorwheel;
39+
public var positionXStepper:UINumericStepper;
40+
public var positionYStepper:UINumericStepper;
41+
public var cameraXStepper:UINumericStepper;
42+
public var cameraYStepper:UINumericStepper;
43+
public var scaleStepper:UINumericStepper;
44+
public var singTimeStepper:UINumericStepper;
45+
public var animationsButtonList:UIButtonList<CharacterAnimInfoButton>;
46+
public var isPlayerCheckbox:UICheckbox;
47+
public var isGFCheckbox:UICheckbox;
48+
public var scriptExtension:UITextBox;
49+
public var isShortLived:UICheckbox;
50+
public var loadBefore:UICheckbox;
51+
52+
public var saveButton:UIButton;
53+
public var closeButton:UIButton;
54+
55+
public var onSave:(xml:Xml) -> Void = null;
56+
57+
var template:String =
58+
'<character isPlayer="false" flipX="false" holdTime="4" color="#AF66CE">
59+
<anim name="idle" anim="Dad idle dance" fps="24" loop="false" x="0" y="0"/>
60+
<anim name="singUP" anim="Dad Sing note UP" fps="24" loop="false" x="-6" y="50"/>
61+
<anim name="singLEFT" anim="dad sing note right" fps="24" loop="false" x="-10" y="10"/>
62+
<anim name="singRIGHT" anim="Dad Sing Note LEFT" fps="24" loop="false" x="0" y="27"/>
63+
<anim name="singDOWN" anim="Dad Sing Note DOWN" fps="24" loop="false" x="0" y="-30"/>
64+
</character>';
65+
66+
var curData = {
67+
anim: []
68+
};
69+
70+
function create() {
71+
winTitle = "Creating Character";
72+
winWidth = 1014;
73+
winHeight = 600;
74+
/*
75+
curData = {
76+
anim: []
77+
};
78+
*/
79+
}
80+
81+
function postCreate() {
82+
function addLabelOn(ui, text:String)
83+
add(new UIText(ui.x, ui.y - 24, 0, text));
84+
85+
var title:UIText;
86+
add(title = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Sprite Data", 28));
87+
88+
spriteTextBox = new UITextBox(title.x, title.y + title.height + 38, 'sprite', 200);
89+
spriteTextBox.onChange = (sprite:String) -> {checkSpriteFile(sprite);}
90+
add(spriteTextBox);
91+
addLabelOn(spriteTextBox, "Sprite");
92+
93+
iconTextBox = new UITextBox(spriteTextBox.x + 200 + 26, spriteTextBox.y, 'sprite-icon', 150);
94+
iconTextBox.onChange = (newIcon:String) -> {updateIcon(newIcon);}
95+
add(iconTextBox);
96+
addLabelOn(iconTextBox, "Icon");
97+
98+
updateIcon('face');
99+
100+
gameOverCharTextBox = new UITextBox(iconTextBox.x + 150 + (75 + 12), iconTextBox.y, "bf-dead", 200);
101+
gameOverCharTextBox.onChange = (sprite:String) -> {checkSpriteFile(sprite);}
102+
add(gameOverCharTextBox);
103+
addLabelOn(gameOverCharTextBox, "Game Over Character");
104+
105+
antialiasingCheckbox = new UICheckbox(spriteTextBox.x, spriteTextBox.y + 10 + 32 + 28, "Antialiasing", true);
106+
add(antialiasingCheckbox);
107+
addLabelOn(antialiasingCheckbox, "Antialiased");
108+
109+
flipXCheckbox = new UICheckbox(antialiasingCheckbox.x + 172, spriteTextBox.y + 10 + 32 + 28, "FlipX", false);
110+
add(flipXCheckbox);
111+
addLabelOn(flipXCheckbox, "Flipped");
112+
113+
iconColorWheel = new UIColorwheel(gameOverCharTextBox.x + 200 + 20, gameOverCharTextBox.y, 0xFFFFFFFF);
114+
add(iconColorWheel);
115+
addLabelOn(iconColorWheel, "Icon Color");
116+
117+
add(title = new UIText(spriteTextBox.x, spriteTextBox.y + 10 + 46 + 84, 0, "Character Data", 28));
118+
119+
positionXStepper = new UINumericStepper(title.x, title.y + title.height + 36, 0, 0.001, 2, null, null, 84);
120+
add(positionXStepper);
121+
addLabelOn(positionXStepper, "Position (X,Y)");
122+
123+
add(new UIText(positionXStepper.x + 84 - 32 + 0, positionXStepper.y + 9, 0, ",", 22));
124+
125+
positionYStepper = new UINumericStepper(positionXStepper.x + 84 - 32 + 26, positionXStepper.y, 0, 0.001, 2, null, null, 84);
126+
add(positionYStepper);
127+
128+
cameraXStepper = new UINumericStepper(positionYStepper.x + 36 + 84 - 32, positionYStepper.y, 0, 0.001, 2, null, null, 84);
129+
add(cameraXStepper);
130+
addLabelOn(cameraXStepper, "Camera Position (X,Y)");
131+
132+
add(new UIText(cameraXStepper.x + 84 - 32 + 0, cameraXStepper.y + 9, 0, ",", 22));
133+
134+
cameraYStepper = new UINumericStepper(cameraXStepper.x + 84 - 32 + 26, cameraXStepper.y, 0, 0.001, 2, null, null, 84);
135+
add(cameraYStepper);
136+
137+
scaleStepper = new UINumericStepper(cameraYStepper.x + 84 - 32 + 90, cameraYStepper.y, 1, 0.001, 2, null, null, 74);
138+
add(scaleStepper);
139+
addLabelOn(scaleStepper, "Scale");
140+
141+
singTimeStepper = new UINumericStepper(scaleStepper.x + 74 - 32 + 36, scaleStepper.y, 4, 0.001, 2, null, null, 74);
142+
add(singTimeStepper);
143+
addLabelOn(singTimeStepper, "Sing Duration (Steps)");
144+
145+
animationsButtonList = new UIButtonList/*<CharacterAnimInfoButton>*/(singTimeStepper.x + singTimeStepper.width + 200, singTimeStepper.y, 290, 200, '', FlxPoint.get(280, 35), null, 5);
146+
animationsButtonList.frames = Paths.getFrames('editors/ui/inputbox');
147+
animationsButtonList.cameraSpacing = 0;
148+
animationsButtonList.addButton.callback = function() {
149+
//customPropertiesButtonList.add(new PropertyButton("newProperty", "valueHere", customPropertiesButtonList));
150+
openSubState(new CharacterAnimScreen(null, (_) -> {
151+
if(_ != null) addAnim(_);
152+
}));
153+
}
154+
155+
var tempXML = Xml.parse(template).firstElement();
156+
var c:Int = 0;
157+
for(i in tempXML.elements()) {
158+
var animData = XMLUtil.extractAnimFromXML(i);
159+
addAnim(animData, c);
160+
c++;
161+
}
162+
163+
add(animationsButtonList);
164+
addLabelOn(animationsButtonList, "Animations");
165+
166+
isPlayerCheckbox = new UICheckbox(positionXStepper.x, positionXStepper.y + 10 + 32 + 28, "isPlayer", false);
167+
add(isPlayerCheckbox);
168+
addLabelOn(isPlayerCheckbox, "Is Player");
169+
170+
isGFCheckbox = new UICheckbox(isPlayerCheckbox.x + 128, positionXStepper.y + 10 + 32 + 28, "isGF", false);
171+
add(isGFCheckbox);
172+
addLabelOn(isGFCheckbox, "Is GF");
173+
174+
for (checkbox in [isPlayerCheckbox, isGFCheckbox, antialiasingCheckbox, flipXCheckbox])
175+
{checkbox.y += 4; checkbox.x += 6;}
176+
177+
scriptExtension = new UITextBox(250, 388, "", 200);
178+
add(scriptExtension);
179+
addLabelOn(scriptExtension, "Script Extension");
180+
181+
isShortLived = new UICheckbox(scriptExtension.x, (scriptExtension.y + scriptExtension.bHeight) + 15, "isShortLived", false);
182+
add(isShortLived);
183+
184+
loadBefore = new UICheckbox(isShortLived.x, isShortLived.y + 30, "loadBefore", true);
185+
add(loadBefore);
186+
187+
saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, windowSpr.y + windowSpr.bHeight- 20, "Save & Close", function() {
188+
buildCharacter();
189+
//CharacterCreationScreen.instance = null;
190+
close();
191+
}, 125);
192+
saveButton.x -= saveButton.bWidth;
193+
saveButton.y -= saveButton.bHeight;
194+
195+
closeButton = new UIButton(saveButton.x - 20, saveButton.y, "Close", function() {
196+
if (onSave != null) onSave(null);
197+
//CharacterCreationScreen.instance = null;
198+
close();
199+
}, 125);
200+
closeButton.x -= closeButton.bWidth;
201+
closeButton.color = 0xFFFF0000;
202+
add(closeButton);
203+
add(saveButton);
204+
}
205+
206+
function checkSpriteFile(sprite:String) {
207+
if(sprite != null) {
208+
var spriteFile = Paths.image("characters/" + sprite); // Common spritesheet file
209+
var spriteAtlas = Path.withoutExtension(spriteFile) + "/Animation.json"; // Texture Atlas
210+
if(!Assets.exists(spriteFile) && !Assets.exists(spriteAtlas)) {
211+
openSubState(new UIWarningSubstate("Missing Sprite file!", "The provided filename doesn't exist or is inaccessible. Try again.", [
212+
{label: "Ok", color: 0xFFFF0000, onClick: function(t) {}}
213+
]));
214+
}
215+
}
216+
}
217+
218+
function updateIcon(icon:String) {
219+
if (iconSprite == null) add(iconSprite = new FlxSprite());
220+
/*
221+
if (iconSprite.animation.exists(icon)) return;
222+
@:privateAccess iconSprite.animation.clearAnimations();
223+
*/
224+
var path:String = Paths.image("icons/" + icon);
225+
226+
if (!Assets.exists(path)) path = Paths.image('icons/face');
227+
228+
iconSprite.loadGraphic(path, true, 150, 150);
229+
iconSprite.animation.add(icon, [0], 0, false);
230+
iconSprite.antialiasing = true;
231+
iconSprite.animation.play(icon);
232+
233+
iconSprite.scale.set(0.5, 0.5);
234+
iconSprite.updateHitbox();
235+
iconSprite.setPosition(iconTextBox.x + 150 + 8, (iconTextBox.y + 16) - (iconSprite.height/2));
236+
}
237+
238+
function saveCharacterInfo() {
239+
/*
240+
for (stepper in [positionXStepper, positionYStepper, cameraXStepper, cameraYStepper, singTimeStepper, scaleStepper])
241+
@:privateAccess stepper.__onChange(stepper.label.text);
242+
*/
243+
var xml = Xml.createElement("character");
244+
// Avoids redundant default values
245+
if(positionXStepper.value != 0) xml.set("x", Std.string(positionXStepper.value));
246+
if(positionYStepper.value != 0) xml.set("y", Std.string(positionYStepper.value));
247+
if(gameOverCharTextBox.label.text != Character.FALLBACK_DEAD_CHARACTER) xml.set("gameOverChar", gameOverCharTextBox.label.text);
248+
if(cameraXStepper.value != 0) xml.set("camx", Std.string(cameraXStepper.value));
249+
if(cameraXStepper.value != 0) xml.set("camy", Std.string(cameraYStepper.value));
250+
if(singTimeStepper.value != 4) xml.set("holdTime", Std.string(singTimeStepper.value));
251+
if(flipXCheckbox.checked) xml.set("flipX", Std.string(flipXCheckbox.checked));
252+
if(scaleStepper.value != 1) xml.set("scale", Std.string(scaleStepper.value));
253+
if (iconColorWheel.colorChanged)
254+
xml.set("color", iconColorWheel.curColorString);
255+
256+
xml.set("isPlayer", isPlayerCheckbox.checked ? "true" : "false");
257+
xml.set("icon", iconTextBox.label.text);
258+
xml.set("antialiasing", antialiasingCheckbox.checked ? "true" : "false");
259+
xml.set("sprite", spriteTextBox.label.text);
260+
261+
for (anim in curData.anim)
262+
{
263+
var animXml:Xml = Xml.createElement('anim');
264+
animXml.set("name", anim.name);
265+
animXml.set("anim", anim.anim);
266+
animXml.set("loop", Std.string(anim.loop));
267+
animXml.set("fps", Std.string(anim.fps));
268+
//var offset:FlxPoint = character.getAnimOffset(anim.name);
269+
var offset:FlxPoint = FlxPoint.get(anim.x, anim.y);
270+
animXml.set("x", Std.string(offset.x));
271+
animXml.set("y", Std.string(offset.y));
272+
offset.put();
273+
274+
if (anim.indices.length > 0)
275+
animXml.set("indices", CoolUtil.formatNumberRange(anim.indices));
276+
xml.addChild(animXml);
277+
}
278+
279+
if(StringTools.trim(scriptExtension.label.text) != "") {
280+
var extXml:Xml = Xml.createElement('extension');
281+
var _scriptFile:String = StringTools.trim(scriptExtension.label.text);
282+
var _scriptFolder:String = null;
283+
var _scriptPath:Array<String> = _scriptFile.split("/");
284+
if(_scriptPath.length > 1) {
285+
_scriptFile = _scriptPath.pop();
286+
_scriptFolder = _scriptPath.join("/") + "/";
287+
}
288+
extXml.set("script", _scriptFile);
289+
if(_scriptFolder != null) extXml.set("folder", _scriptFolder);
290+
if(isShortLived.checked) extXml.set("isShortLived", Std.string(isShortLived.checked));
291+
if(!loadBefore.checked) extXml.set("loadBefore", Std.string(loadBefore.checked));
292+
xml.addChild(extXml);
293+
}
294+
295+
// End of writing XML, time to save it
296+
var data:String = "<!DOCTYPE codename-engine-character>\n" + Printer.print(xml, true);
297+
var fileDialog = new FileDialog();
298+
fileDialog.onCancel.add(function() close());
299+
fileDialog.onSelect.add(function(str)
300+
{
301+
CoolUtil.safeSaveFile(str, data);
302+
close();
303+
FlxG.resetState();
304+
});
305+
var fullPath = FileSystem.fullPath(Paths.xml('characters/character'));
306+
fileDialog.browse(FileDialogType.SAVE, "xml", fullPath);
307+
if (onSave != null) onSave(xml);
308+
}
309+
310+
function addAnim(animData:AnimData, animID:Int = -1) {
311+
var newButton = new CharacterAnimInfoButton(0, 0, animData.name, FlxPoint.get(animData.x,animData.y));
312+
// Edit/Delete callbacks
313+
newButton.editButton.callback = function() {
314+
editAnim(newButton.anim);
315+
};
316+
newButton.deleteButton.callback = function() {
317+
deleteAnim(newButton.anim);
318+
};
319+
320+
if (animID == -1){
321+
animationsButtonList.add(newButton);
322+
curData.anim.push(animData);
323+
}
324+
else {
325+
animationsButtonList.insert(newButton, animID);
326+
curData.anim.insert(animID, animData);
327+
}
328+
}
329+
330+
public function editAnim(name:String) {
331+
var _anim:AnimData = null;
332+
for(anim in curData.anim) {
333+
if(anim.name == name) {
334+
_anim = anim;
335+
break;
336+
}
337+
}
338+
openSubState(new CharacterAnimScreen(_anim, (_) -> {
339+
if(_ != null) _edit_anim(name, _anim, _);
340+
}));
341+
}
342+
343+
function _edit_anim(name:String, oldAnimData:AnimData, animData:AnimData) {
344+
var buttoner:CharacterAnimInfoButton = null;
345+
for (button in animationsButtonList.buttons.members)
346+
if (button.anim == name) buttoner = button;
347+
buttoner.updateInfo(animData.name);
348+
349+
//Replace the old data
350+
var index = curData.anim.indexOf(oldAnimData);
351+
curData.anim[index] = animData;
352+
}
353+
354+
public function deleteAnim(name:String) {
355+
for(button in animationsButtonList.buttons.members)
356+
{
357+
if(button.anim == name)
358+
animationsButtonList.remove(button);
359+
}
360+
for (anim in curData.anim)
361+
{
362+
if (anim.name == name)
363+
{
364+
curData.anim.remove(anim);
365+
break;
366+
}
367+
}
368+
}
369+
370+
// ???
371+
function buildCharacter() {
372+
saveCharacterInfo();
373+
}
374+
/*
375+
typedef CharacterCreationData = {
376+
var anim:Array<AnimData>;
377+
}
378+
*/

0 commit comments

Comments
 (0)