Hastily made editor meant for internal use
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<language>
|
||||
<!-- Alphabet Editor -->
|
||||
|
||||
<group name="AlphabetSelection" prefix="alphabetSelection.">
|
||||
<str id="acceptTypeface">Press ACCEPT to edit this typeface.</str>
|
||||
<str id="newTypeface">New Typeface</str>
|
||||
<str id="desc">Select a typeface to edit</str>
|
||||
|
||||
<group name="Warnings" prefix="warnings.">
|
||||
<str id="notImplemented-title">New Typeface: Feature Not Implemented!</str>
|
||||
<str id="notImplemented-body">This feature isn't implemented yet. Please wait for more cne updates to have this functional.\n\n\n- Codename Devs</str>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<group name="AlphabetEditor" prefix="alphabetEditor.">
|
||||
<str id="name">Alphabet Editor</str>
|
||||
|
||||
<group name="TopBar">
|
||||
<str id="topBar.file">File</str>
|
||||
<group name="FileMenu" prefix="file.">
|
||||
<str id="new">New</str>
|
||||
<str id="save">Save</str>
|
||||
<str id="saveAs">Save As...</str>
|
||||
<str id="exit">Exit</str>
|
||||
</group>
|
||||
|
||||
<str id="topBar.edit">Edit</str>
|
||||
<group name="EditMenu" prefix="edit.">
|
||||
<str id="undo">Undo</str>
|
||||
<str id="redo">Redo</str>
|
||||
</group>
|
||||
|
||||
<str id="topBar.glyph">Glyph</str>
|
||||
<group name="GlyphMenu" prefix="glyph.">
|
||||
<str id="newGlyph">New Glyph</str>
|
||||
<str id="editGlyph">Edit Glyph</str>
|
||||
<str id="deleteGlyph">Delete Glyph</str>
|
||||
</group>
|
||||
|
||||
<str id="topBar.offset">Offsets</str>
|
||||
<group name="OffsetsMenu" prefix="offset.">
|
||||
<str id="moveLeft">Move Left</str>
|
||||
<str id="moveUp">Move Up</str>
|
||||
<str id="moveDown">Move Down</str>
|
||||
<str id="moveRight">Move Right</str>
|
||||
<str id="moveExtraLeft">Move Extra Left</str>
|
||||
<str id="moveExtraUp">Move Extra Up</str>
|
||||
<str id="moveExtraDown">Move Extra Down</str>
|
||||
<str id="moveExtraRight">Move Extra Right</str>
|
||||
<str id="clearOffsets">Clear Offsets</str>
|
||||
</group>
|
||||
|
||||
<str id="topBar.view">View</str>
|
||||
<group name="ViewMenu" prefix="view.">
|
||||
<str id="zoomIn">Zoom in</str>
|
||||
<str id="zoomOut">Zoom out</str>
|
||||
<str id="resetZoom">Reset Zoom</str>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</language>
|
||||
@@ -8,6 +8,12 @@ class EditorPicker extends MusicBeatSubstate {
|
||||
|
||||
// Name is for backwards compatability, dont use it, use id instead
|
||||
public var options:Array<Editor> = [
|
||||
{
|
||||
name: "Alphabet Editor",
|
||||
id: "alphabetEditor",
|
||||
iconID: -1,
|
||||
state: funkin.editors.alphabet.AlphabetSelection
|
||||
},
|
||||
{
|
||||
name: "Chart Editor",
|
||||
id: "charter",
|
||||
@@ -186,8 +192,12 @@ class EditorPickerOption extends FlxTypedSpriteGroup<FlxSprite> {
|
||||
FlxG.mouse.visible = true;
|
||||
iconSpr = new FlxSprite();
|
||||
iconSpr.loadGraphic(Paths.image('editors/icons'), true, 128, 128);
|
||||
iconSpr.animation.add("icon", [iconID], 24, true);
|
||||
iconSpr.animation.play("icon");
|
||||
if(iconID >= 0) {
|
||||
iconSpr.animation.add("icon", [iconID], 24, true);
|
||||
iconSpr.animation.play("icon");
|
||||
} else {
|
||||
iconSpr.exists = false;
|
||||
}
|
||||
iconSpr.antialiasing = true;
|
||||
if (height < 150) {
|
||||
iconSpr.scale.set(height / 150, height / 150);
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
package funkin.editors.alphabet;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.backend.system.framerate.Framerate;
|
||||
import funkin.backend.utils.XMLUtil.AnimData;
|
||||
import funkin.editors.ui.UIContextMenu.UIContextMenuOption;
|
||||
import funkin.game.Character;
|
||||
import haxe.xml.Access;
|
||||
import haxe.xml.Printer;
|
||||
|
||||
class AlphabetEditor extends UIState {
|
||||
static var __typeface:String;
|
||||
|
||||
public static var instance(get, null):AlphabetEditor;
|
||||
|
||||
private static inline function get_instance()
|
||||
return FlxG.state is AlphabetEditor ? cast FlxG.state : null;
|
||||
|
||||
public var topMenu:Array<UIContextMenuOption>;
|
||||
public var topMenuSpr:UITopMenu;
|
||||
|
||||
public var uiGroup:FlxTypedGroup<FlxSprite> = new FlxTypedGroup<FlxSprite>();
|
||||
|
||||
var editorCamera:FlxCamera;
|
||||
var uiCamera:FlxCamera;
|
||||
|
||||
public function new(typeface:String) {
|
||||
super();
|
||||
if (typeface != null) __typeface = typeface;
|
||||
}
|
||||
|
||||
inline function translate(id:String, ?args:Array<Dynamic>)
|
||||
return TU.translate("alphabetEditor." + id, args);
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
|
||||
WindowUtils.suffix = " (" + translate("name") + ")";
|
||||
SaveWarning.selectionClass = AlphabetSelection;
|
||||
SaveWarning.saveFunc = () -> {_file_save(null);};
|
||||
|
||||
topMenu = [
|
||||
{
|
||||
label: translate("topBar.file"),
|
||||
childs: [
|
||||
{
|
||||
label: translate("file.save"),
|
||||
keybind: [CONTROL, S],
|
||||
onSelect: _file_save
|
||||
},
|
||||
{
|
||||
label: translate("file.saveAs"),
|
||||
keybind: [CONTROL, SHIFT, S],
|
||||
onSelect: _file_saveas
|
||||
},
|
||||
null,
|
||||
{
|
||||
label: translate("file.exit"),
|
||||
onSelect: _file_exit
|
||||
}
|
||||
]
|
||||
// TODO: add more options
|
||||
},
|
||||
{
|
||||
label: translate("topBar.glyph"),
|
||||
childs: [
|
||||
{
|
||||
label: translate("glyph.newGlyph"),
|
||||
//onSelect: _glyph_new
|
||||
},
|
||||
{
|
||||
label: translate("glyph.editGlyph"),
|
||||
//onSelect: _glyph_edit
|
||||
},
|
||||
{
|
||||
label: translate("glyph.deleteGlyph"),
|
||||
//onSelect: _glyph_delete
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: translate("topBar.view"),
|
||||
childs: [
|
||||
{
|
||||
label: translate("view.zoomIn"),
|
||||
keybind: [CONTROL, NUMPADPLUS],
|
||||
//onSelect: _view_zoomin
|
||||
},
|
||||
{
|
||||
label: translate("view.zoomOut"),
|
||||
keybind: [CONTROL, NUMPADMINUS],
|
||||
//onSelect: _view_zoomout
|
||||
},
|
||||
{
|
||||
label: translate("view.resetZoom"),
|
||||
keybind: [CONTROL, NUMPADZERO],
|
||||
//onSelect: _view_zoomreset
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: " ",
|
||||
childs: [
|
||||
{
|
||||
label: "Tape",
|
||||
//onSelect: _tape
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Move Tape Left",
|
||||
childs: [
|
||||
{
|
||||
label: "Tape",
|
||||
//onSelect: _tape
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Move Tape Right",
|
||||
childs: [
|
||||
{
|
||||
label: "Tape",
|
||||
//onSelect: _tape
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
editorCamera = FlxG.camera;
|
||||
|
||||
uiCamera = new FlxCamera();
|
||||
uiCamera.bgColor = 0;
|
||||
|
||||
FlxG.cameras.add(uiCamera);
|
||||
|
||||
var bg = new FlxSprite(0, 0).makeSolid(Std.int(FlxG.width + 100), Std.int(FlxG.height + 100), 0xFF7f7f7f);
|
||||
bg.cameras = [editorCamera];
|
||||
bg.scrollFactor.set();
|
||||
bg.screenCenter();
|
||||
add(bg);
|
||||
|
||||
topMenuSpr = new UITopMenu(topMenu);
|
||||
topMenuSpr.cameras = uiGroup.cameras = [uiCamera];
|
||||
|
||||
//var alphabet:Alphabet = new Alphabet(0, 0, __typeface);
|
||||
//add(alphabet);
|
||||
|
||||
var xml = Xml.parse(Assets.getText(Paths.xml('alphabet/$__typeface'))).firstElement();
|
||||
var spritesheet = null;
|
||||
for(node in xml.elements()) {
|
||||
if (node.nodeName == "spritesheet") {
|
||||
spritesheet = node.firstChild().nodeValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var useColorOffsets = xml.get("useColorOffsets").getDefault("false") == "true";
|
||||
|
||||
|
||||
// todo fix crash if invalid spritesheet;
|
||||
var alphabetFrames = Paths.getFrames(spritesheet);
|
||||
|
||||
var allChars = "";
|
||||
for(frame in alphabetFrames.frames) {
|
||||
var secondChar = frame.name.charAt(1);
|
||||
if(secondChar != " ") continue;
|
||||
if(allChars.contains(frame.name.charAt(0))) continue;
|
||||
allChars += frame.name.charAt(0);
|
||||
}
|
||||
|
||||
var letterSprites:Array<FlxSprite> = [];
|
||||
for(letter in allChars.split("")) {
|
||||
var spr = new FlxSprite(0, 0);
|
||||
spr.frames = alphabetFrames;
|
||||
spr.antialiasing = true;
|
||||
spr.animation.addByPrefix("letter", letter, 24);
|
||||
spr.animation.play("letter");
|
||||
add(spr);
|
||||
letterSprites.push(spr);
|
||||
}
|
||||
|
||||
var length = letterSprites.length;
|
||||
var letterWidth = 70;
|
||||
var letterHeight = 80;
|
||||
//var width = 10;
|
||||
//var totalWidth = 10 * 70;
|
||||
//for(i in 0...length) {
|
||||
// var letter = letterSprites[i];
|
||||
// var x = i % width * 70 + (FlxG.width / 2 - totalWidth / 2);
|
||||
// var y = Std.int(i / width) * 80 + 100;
|
||||
// letter.setPosition(x, y);
|
||||
//}
|
||||
|
||||
var randomIndex = FlxG.random.int(0, length-1);
|
||||
for(i in 0...length) {
|
||||
var letter = letterSprites[i];
|
||||
letter.alpha = 0.2;
|
||||
}
|
||||
letterSprites[randomIndex].alpha = 1;
|
||||
|
||||
for(i in 0...length) {
|
||||
var letter = letterSprites[i];
|
||||
letter.x = i * letterWidth - randomIndex * letterWidth + (FlxG.width / 2 - letterWidth / 2);
|
||||
letter.y = 50;
|
||||
}
|
||||
|
||||
var bigletter = new FlxSprite(0, 0);
|
||||
bigletter.frames = alphabetFrames;
|
||||
bigletter.antialiasing = true;
|
||||
bigletter.animation.addByPrefix("letter", allChars.charAt(randomIndex), 24);
|
||||
bigletter.animation.play("letter");
|
||||
bigletter.updateHitbox();
|
||||
bigletter.screenCenter();
|
||||
bigletter.scale.set(4, 4);
|
||||
add(bigletter);
|
||||
|
||||
var infoWindow = new GlyphInfoWindow();
|
||||
infoWindow.info.text = [
|
||||
"Char: " + allChars.charAt(randomIndex),
|
||||
"Anim Name: " + allChars.charAt(randomIndex) + " bold0",
|
||||
"X Offset: " + 0,
|
||||
"Y Offset: " + 0,
|
||||
"ScaleX: " + 1,
|
||||
"ScaleY: " + 1,
|
||||
"Angle: " + 0,
|
||||
].join('\n');
|
||||
uiGroup.add(infoWindow);
|
||||
|
||||
var leftWindow = new UIWindow(30, 720 - 170 - 30, 230, 170, "Components:");
|
||||
leftWindow.members.push({
|
||||
var info = new UIText(leftWindow.x + 28, leftWindow.y + 46, 400, "");
|
||||
info.text = "[0] Letter (" + allChars.charAt(randomIndex) + ")";
|
||||
info.alignment = LEFT;
|
||||
info;
|
||||
});
|
||||
leftWindow.members.push(new UIButton(leftWindow.x + 28, leftWindow.y + 170 - 40, "Add", function () {}));
|
||||
uiGroup.add(leftWindow);
|
||||
|
||||
add(topMenuSpr);
|
||||
add(uiGroup);
|
||||
|
||||
if(Framerate.isLoaded) {
|
||||
Framerate.fpsCounter.alpha = 0.4;
|
||||
Framerate.memoryCounter.alpha = 0.4;
|
||||
Framerate.codenameBuildField.alpha = 0.4;
|
||||
}
|
||||
|
||||
DiscordUtil.call("onEditorLoaded", ["Alphabet Editor", __typeface]);
|
||||
}
|
||||
|
||||
override function destroy() {
|
||||
super.destroy();
|
||||
if(Framerate.isLoaded) {
|
||||
Framerate.fpsCounter.alpha = 1;
|
||||
Framerate.memoryCounter.alpha = 1;
|
||||
Framerate.codenameBuildField.alpha = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
if (true) {
|
||||
if(FlxG.keys.justPressed.ANY)
|
||||
UIUtil.processShortcuts(topMenu);
|
||||
}
|
||||
|
||||
if(FlxG.keys.pressed.J) {
|
||||
editorCamera.scroll.x -= 100 * elapsed;
|
||||
}
|
||||
if(FlxG.keys.pressed.L) {
|
||||
editorCamera.scroll.x += 100 * elapsed;
|
||||
}
|
||||
if(FlxG.keys.pressed.I) {
|
||||
editorCamera.scroll.y -= 100 * elapsed;
|
||||
}
|
||||
if(FlxG.keys.pressed.K) {
|
||||
editorCamera.scroll.y += 100 * elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
function _file_save(_) {
|
||||
#if sys
|
||||
CoolUtil.safeSaveFile(
|
||||
'${Paths.getAssetsRoot()}/data/alphabet/${__typeface}.xml',
|
||||
""//alphabet.buildXML()
|
||||
);
|
||||
#else
|
||||
_file_saveas(_);
|
||||
#end
|
||||
}
|
||||
|
||||
function _file_saveas(_) {
|
||||
openSubState(new SaveSubstate(""/*alphabet.buildXML()*/, {
|
||||
defaultSaveFile: '${__typeface}.xml'
|
||||
}));
|
||||
}
|
||||
|
||||
function _file_exit(_) {
|
||||
/*if (undos.unsaved) SaveWarning.triggerWarning();
|
||||
else */FlxG.switchState(new AlphabetSelection());
|
||||
}
|
||||
}
|
||||
|
||||
class GlyphInfoWindow extends UIWindow {
|
||||
public var info:UIText;
|
||||
public function new() {
|
||||
var width = 230;
|
||||
var height = 170;
|
||||
var margin = 30;
|
||||
super(FlxG.width - width - margin, FlxG.height - height - margin, width, height, "Glyph Info");
|
||||
|
||||
info = new UIText(x + 28, y + 46, 400, "");
|
||||
info.alignment = LEFT;
|
||||
members.push(info);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package funkin.editors.alphabet;
|
||||
|
||||
import haxe.xml.Access;
|
||||
import funkin.game.Character;
|
||||
import funkin.options.OptionsScreen;
|
||||
import funkin.options.type.IconOption;
|
||||
import funkin.options.type.NewOption;
|
||||
import funkin.options.type.TextOption;
|
||||
import funkin.options.type.OptionType;
|
||||
import haxe.io.Path;
|
||||
|
||||
class AlphabetSelection extends EditorTreeMenu
|
||||
{
|
||||
inline function translate(id:String, ?args:Array<Dynamic>)
|
||||
return TU.translate("alphabetSelection." + id, args);
|
||||
|
||||
public override function create()
|
||||
{
|
||||
bgType = "charter";
|
||||
super.create();
|
||||
|
||||
var modsList:Array<String> = [];
|
||||
for(file in Paths.getFolderContent('data/alphabet/', true, BOTH)) // mods ? MODS : BOTH
|
||||
if (Path.extension(file) == "xml") modsList.push(CoolUtil.getFilename(file));
|
||||
|
||||
var list:Array<OptionType> = [
|
||||
for (typeface in modsList)
|
||||
new AlphabetIconOption(typeface, translate("acceptTypeface"), typeface, function() {
|
||||
FlxG.switchState(new AlphabetEditor(typeface));
|
||||
})
|
||||
];
|
||||
|
||||
var newChar = translate("newTypeface");
|
||||
list.insert(0, new NewOption(newChar, newChar, function() {
|
||||
openSubState(new UIWarningSubstate(translate("warnings.notImplemented-title"), translate("warnings.notImplemented-body"), [
|
||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}}
|
||||
]));
|
||||
}));
|
||||
|
||||
main = new OptionsScreen(TU.translate("alphabetEditor.name"), translate("desc"), list);
|
||||
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Alphabet Editor"]);
|
||||
}
|
||||
|
||||
override function createPost() {
|
||||
super.createPost();
|
||||
|
||||
main.changeSelection(1);
|
||||
}
|
||||
}
|
||||
|
||||
class AlphabetIconOption extends TextOption {
|
||||
public var iconSpr:FlxSprite;
|
||||
|
||||
public function new(name:String, desc:String, typeface:String, callback:Void->Void) {
|
||||
super(name, desc, callback);
|
||||
|
||||
var xml = Xml.parse(Assets.getText(Paths.xml('alphabet/$typeface'))).firstElement();
|
||||
var spritesheet = null;
|
||||
for(node in xml.elements()) {
|
||||
if (node.nodeName == "spritesheet") {
|
||||
spritesheet = node.firstChild().nodeValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var useColorOffsets = xml.get("useColorOffsets").getDefault("false") == "true";
|
||||
|
||||
|
||||
// todo fix crash if invalid spritesheet;
|
||||
|
||||
iconSpr = new FlxSprite();
|
||||
iconSpr.frames = Paths.getFrames(spritesheet);
|
||||
iconSpr.antialiasing = true;
|
||||
var frameToUse = iconSpr.frames.frames[0];
|
||||
for(frame in iconSpr.frames.frames) {
|
||||
if (frame.name.toUpperCase().startsWith("A")) {
|
||||
frameToUse = frame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iconSpr.frame = frameToUse;
|
||||
if(useColorOffsets) {
|
||||
iconSpr.colorTransform.color = -1;
|
||||
}
|
||||
iconSpr.setPosition(90 - iconSpr.width - 20, (__text.height - iconSpr.height) / 2);
|
||||
add(iconSpr);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user