Options Rewrite WIP All Editor Menus Done
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
@@ -46,7 +46,9 @@
|
||||
<str id="acceptDifficulty">Press ACCEPT to edit the chart for the selected difficulty.</str>
|
||||
<str id="selectDifficulty">Select a difficulty to continue.</str>
|
||||
<str id="newDifficulty">New Difficulty</str>
|
||||
<str id="newDifficultyDesc">Press ACCEPT to create a new chart difficulty.</str>
|
||||
<str id="newSong">New Song</str>
|
||||
<str id="newSongDesc">Press ACCEPT to create a new song.</str>
|
||||
</group>
|
||||
|
||||
<group name="ChartCreationScreen" prefix="chartCreation.">
|
||||
@@ -435,6 +437,11 @@
|
||||
<str id="win-title">Creating New Character</str>
|
||||
<str id="charName">Character Name $* Required$</str>
|
||||
<str id="charImgName">Character Image File $* Required$</str>
|
||||
|
||||
<group name="Warnings" prefix="warnings.">
|
||||
<str id="char-exists-title">Creating Character: Error!</str>
|
||||
<str id="char-exists-body">The character you are trying to create already exists, if you would like to override it delete the character first!</str>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -442,6 +449,7 @@
|
||||
<group name="AlphabetSelection" prefix="selection.">
|
||||
<str id="acceptTypeface">Press ACCEPT to edit this typeface.</str>
|
||||
<str id="newTypeface">New Typeface</str>
|
||||
<str id="newTypefaceDesc">Press ACCEPT to create a new typeface.</str>
|
||||
<str id="desc">Select a typeface to edit</str>
|
||||
|
||||
<group name="Warnings" prefix="warnings.">
|
||||
@@ -554,6 +562,11 @@
|
||||
<str id="title">Stage Info</str>
|
||||
<str id="stageName">Stage Name</str>
|
||||
<str id="stagePath">Stage Path</str>
|
||||
|
||||
<group name="Warnings" prefix="warnings.">
|
||||
<str id="stage-exists-title">Creating Stage: Error!</str>
|
||||
<str id="stage-exists-body">The stage you are trying to create alreadly exists, if you would like to override it delete the stage first!</str>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<group name="StageInfoScreen" prefix="stageInfoScreen">
|
||||
|
||||
@@ -1,18 +1,57 @@
|
||||
package funkin.editors;
|
||||
|
||||
import funkin.backend.utils.NativeAPI;
|
||||
import funkin.options.OptionsScreen;
|
||||
import funkin.options.TreeMenu;
|
||||
import funkin.options.TreeMenuScreen;
|
||||
import funkin.options.type.*;
|
||||
|
||||
class DebugOptions extends TreeMenu {
|
||||
public override function create() {
|
||||
var bg:FlxSprite;
|
||||
|
||||
override function create() {
|
||||
super.create();
|
||||
UIState.setResolutionAware();
|
||||
|
||||
add(bg = new FlxSprite().loadAnimatedGraphic(Paths.image('menus/menuBGBlue')));
|
||||
bg.antialiasing = true;
|
||||
bg.scrollFactor.set();
|
||||
updateBG();
|
||||
|
||||
addMenu(new TreeMenuScreen('DebugOptions.title', 'DebugOptions.desc'));
|
||||
|
||||
FlxG.camera.fade(0xFF000000, 0.5, true);
|
||||
}
|
||||
|
||||
public function updateBG() {
|
||||
var scaleX:Float = FlxG.width / bg.width;
|
||||
var scaleY:Float = FlxG.height / bg.height;
|
||||
bg.scale.x = bg.scale.y = Math.max(scaleX, scaleY) * 1.15;
|
||||
bg.screenCenter();
|
||||
}
|
||||
|
||||
override function onResize(width:Int, height:Int) {
|
||||
super.onResize(width, height);
|
||||
if (!UIState.resolutionAware) return;
|
||||
|
||||
updateBG();
|
||||
}
|
||||
}
|
||||
|
||||
class DebugOptionsScreen extends OptionsScreen {
|
||||
class DebugOptionsScreen extends TreeMenuScreen {
|
||||
public function new() {
|
||||
super('DebugOptions.title', 'DebugOptions.desc', 'DebugOptions.');
|
||||
|
||||
#if windows
|
||||
add(new TextOption(getNameID("showConsole"), getDescID("showConsole"), () -> NativeAPI.allocConsole()));
|
||||
#end
|
||||
add(new Checkbox(getNameID("editorsResizable"), getDescID("editorsResizable"), "editorsResizable"));
|
||||
add(new Checkbox(getNameID("bypassEditorsResize"), getDescID("bypassEditorsResize"), "bypassEditorsResize"));
|
||||
add(new Checkbox(getNameID("editorSFX"), getDescID("editorSFX"), "editorSFX"));
|
||||
add(new Checkbox(getNameID("editorPrettyPrint"), getDescID("editorPrettyPrint"), "editorPrettyPrint"));
|
||||
add(new Checkbox(getNameID("intensiveBlur"), getDescID("intensiveBlur"), "intensiveBlur"));
|
||||
add(new Checkbox(getNameID("charterAutoSaves"), getDescID("charterAutoSaves"), "charterAutoSaves"));
|
||||
add(new NumOption(getNameID("charterAutoSaveTime"), getDescID("charterAutoSaveTime"), 60, 60*10, 1, "charterAutoSaveTime"));
|
||||
add(new NumOption(getNameID("charterAutoSaveWarningTime"), getDescID("charterAutoSaveWarningTime"), 0, 15, 1, "charterAutoSaveWarningTime"));
|
||||
add(new Checkbox(getNameID("charterAutoSavesSeparateFolder"), getDescID("charterAutoSavesSeparateFolder"), "charterAutoSavesSeparateFolder"));
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,25 @@
|
||||
package funkin.editors;
|
||||
|
||||
import flixel.addons.display.FlxBackdrop;
|
||||
import funkin.menus.MainMenuState;
|
||||
import funkin.options.*;
|
||||
import funkin.options.type.OptionType;
|
||||
|
||||
class EditorTreeMenu extends TreeMenu {
|
||||
class EditorTreeMenu extends funkin.options.TreeMenu {
|
||||
public var bg:FlxBackdrop;
|
||||
public var bgType:String = "default";
|
||||
public var bgMovement:FlxPoint = new FlxPoint();
|
||||
|
||||
public var main:OptionsScreen;
|
||||
|
||||
public override function create() {
|
||||
override function create() {
|
||||
super.create();
|
||||
|
||||
UIState.setResolutionAware();
|
||||
|
||||
FlxG.camera.fade(0xFF000000, 0.5, true);
|
||||
}
|
||||
|
||||
bg = new FlxBackdrop();
|
||||
override function createPost() {
|
||||
super.createPost();
|
||||
add(bg = new FlxBackdrop());
|
||||
bg.loadGraphic(Paths.image('editors/bgs/${bgType}'));
|
||||
bg.antialiasing = true;
|
||||
setBackgroundRotation(-5);
|
||||
add(bg);
|
||||
}
|
||||
|
||||
public inline function setBackgroundRotation(rotation:Float) {
|
||||
@@ -30,11 +27,47 @@ class EditorTreeMenu extends TreeMenu {
|
||||
bg.velocity.set(85, 0).degrees = bg.rotation;
|
||||
}
|
||||
|
||||
public override function exit() {
|
||||
FlxG.switchState(new MainMenuState());
|
||||
override function exit() {
|
||||
FlxG.switchState(new funkin.menus.MainMenuState());
|
||||
}
|
||||
|
||||
public function onMenuChange() {
|
||||
|
||||
override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
bg.colorTransform.redOffset = lerp(bg.colorTransform.redOffset, 0, 0.0625);
|
||||
bg.colorTransform.greenOffset = lerp(bg.colorTransform.greenOffset, 0, 0.0625);
|
||||
bg.colorTransform.blueOffset = lerp(bg.colorTransform.blueOffset, 0, 0.0625);
|
||||
bg.colorTransform.redMultiplier = lerp(bg.colorTransform.redMultiplier, 1, 0.0625);
|
||||
bg.colorTransform.greenMultiplier = lerp(bg.colorTransform.greenMultiplier, 1, 0.0625);
|
||||
bg.colorTransform.blueMultiplier = lerp(bg.colorTransform.blueMultiplier, 1, 0.0625);
|
||||
}
|
||||
|
||||
override function menuChanged() @:privateAccess {
|
||||
super.menuChanged();
|
||||
if (previousMenus.length > 0) return; // selected a sub-menu
|
||||
|
||||
var prev = tree[tree.length - 2];
|
||||
if (prev == null || prev.curOption == null || !(prev.curOption is OptionType)) return;
|
||||
|
||||
// small flashbang
|
||||
var color = cast(prev.curOption, OptionType).editorFlashColor;
|
||||
bg.colorTransform.redOffset = 0.25 * color.red;
|
||||
bg.colorTransform.greenOffset = 0.25 * color.green;
|
||||
bg.colorTransform.blueOffset = 0.25 * color.blue;
|
||||
bg.colorTransform.redMultiplier = FlxMath.lerp(1, color.redFloat, 0.25);
|
||||
bg.colorTransform.greenMultiplier = FlxMath.lerp(1, color.greenFloat, 0.25);
|
||||
bg.colorTransform.blueMultiplier = FlxMath.lerp(1, color.blueFloat, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
class EditorTreeMenuScreen extends funkin.options.TreeMenuScreen {
|
||||
public function new(name:String, desc:String, ?prefix:String, ?objects:Array<FlxSprite>,
|
||||
?newButton:String, ?newButtonDesc:String, ?newCallback:Void->Void)
|
||||
{
|
||||
super(name, desc, prefix, objects);
|
||||
if (newCallback != null) {
|
||||
insert(0, new funkin.options.type.NewOption(getID(newButton), getID(newButtonDesc), newCallback));
|
||||
curSelected = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,35 @@
|
||||
package funkin.editors.alphabet;
|
||||
|
||||
import haxe.io.Path;
|
||||
import haxe.xml.Access;
|
||||
import funkin.game.Character;
|
||||
import funkin.options.OptionsScreen;
|
||||
import funkin.options.type.IconOption;
|
||||
import funkin.editors.EditorTreeMenu;
|
||||
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("editor.alphabet.selection." + id, args);
|
||||
|
||||
public override function create()
|
||||
{
|
||||
bgType = "charter";
|
||||
class AlphabetSelection extends EditorTreeMenu {
|
||||
override function create() {
|
||||
super.create();
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Alphabet Editor"]);
|
||||
addMenu(new AlphabetSelectionScreen());
|
||||
}
|
||||
}
|
||||
|
||||
class AlphabetSelectionScreen extends EditorTreeMenuScreen {
|
||||
public function new() {
|
||||
super('editor.alphabet.name', 'editor.alphabet.selection.desc', 'editor.alphabet.selection', 'newTypeface', 'newTypefaceDesc', () -> {
|
||||
parent.openSubState(new UIWarningSubstate(translate('warnings.notImplemented-title'), translate('warnings.notImplemented-body'), [
|
||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}}
|
||||
]));
|
||||
});
|
||||
|
||||
var modsList:Array<String> = [];
|
||||
for(file in Paths.getFolderContent('data/alphabet/', true, BOTH)) // mods ? MODS : BOTH
|
||||
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("editor.alphabet.name"), translate("desc"), list);
|
||||
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Alphabet Editor"]);
|
||||
}
|
||||
|
||||
override function createPost() {
|
||||
super.createPost();
|
||||
|
||||
main.changeSelection(1);
|
||||
for (typeface in modsList)
|
||||
add(new AlphabetIconOption(typeface, getID('acceptTypeface'), typeface, () -> FlxG.switchState(new AlphabetEditor(typeface))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +41,7 @@ class AlphabetIconOption extends TextOption {
|
||||
|
||||
var xml = Xml.parse(Assets.getText(Paths.xml('alphabet/$typeface'))).firstElement();
|
||||
var spritesheet = null;
|
||||
for(node in xml.elements()) {
|
||||
for (node in xml.elements()) {
|
||||
if (node.nodeName == "spritesheet") {
|
||||
spritesheet = node.firstChild().nodeValue;
|
||||
break;
|
||||
@@ -73,14 +57,14 @@ class AlphabetIconOption extends TextOption {
|
||||
iconSpr.frames = Paths.getFrames(spritesheet);
|
||||
iconSpr.antialiasing = true;
|
||||
var frameToUse = iconSpr.frames.frames[0];
|
||||
for(frame in iconSpr.frames.frames) {
|
||||
for (frame in iconSpr.frames.frames) {
|
||||
if (frame.name.toUpperCase().startsWith("A")) {
|
||||
frameToUse = frame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iconSpr.frame = frameToUse;
|
||||
if(useColorOffsets) {
|
||||
if (useColorOffsets) {
|
||||
iconSpr.colorTransform.color = -1;
|
||||
}
|
||||
iconSpr.setPosition(90 - iconSpr.width - 20, (__text.height - iconSpr.height) / 2);
|
||||
|
||||
@@ -1,81 +1,69 @@
|
||||
package funkin.editors.character;
|
||||
|
||||
import haxe.xml.Printer;
|
||||
import funkin.editors.ui.UIImageExplorer.ImageSaveData;
|
||||
import funkin.game.Character;
|
||||
import funkin.options.OptionsScreen;
|
||||
import funkin.editors.ui.UIImageExplorer.ImageSaveData;
|
||||
import funkin.editors.EditorTreeMenu;
|
||||
import funkin.options.type.IconOption;
|
||||
import funkin.options.type.NewOption;
|
||||
import funkin.options.type.TextOption;
|
||||
import funkin.options.type.OptionType;
|
||||
import funkin.backend.assets.ModsFolder;
|
||||
|
||||
class CharacterSelection extends EditorTreeMenu
|
||||
{
|
||||
inline function translate(id:String, ?args:Array<Dynamic>)
|
||||
return TU.translate("characterSelection." + id, args);
|
||||
class CharacterSelection extends EditorTreeMenu {
|
||||
override function create() {
|
||||
super.create();
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Character Editor"]);
|
||||
addMenu(new CharacterSelectionScreen());
|
||||
}
|
||||
}
|
||||
|
||||
class CharacterSelectionScreen extends EditorTreeMenuScreen {
|
||||
public var modsList:Array<String> = [];
|
||||
|
||||
public override function create()
|
||||
{
|
||||
bgType = "charter";
|
||||
super.create();
|
||||
public function new() {
|
||||
super('editor.character.name', 'characterSelection.desc', 'characterSelection.', 'newCharacter', 'newCharacterDesc', () -> {
|
||||
parent.openSubState(new CharacterCreationScreen(createCharacter));
|
||||
});
|
||||
|
||||
var isMods:Bool = true;
|
||||
modsList = Character.getList(true, true);
|
||||
|
||||
if(modsList.length == 0) {
|
||||
if (modsList.length == 0) {
|
||||
modsList = Character.getList(false, true);
|
||||
isMods = false;
|
||||
}
|
||||
|
||||
function generateList(modsList:Array<String>, isMods:Bool, folderPath:String = ""):Array<OptionType> {
|
||||
var list:Array<OptionType> = [];
|
||||
function generateList(modsList:Array<String>, isMods:Bool, folderPath:String = ""):Array<FlxSprite> {
|
||||
var list:Array<FlxSprite> = [];
|
||||
|
||||
for(char in modsList) {
|
||||
if(char.endsWith("/")) {
|
||||
for (char in modsList) {
|
||||
if (char.endsWith("/")) {
|
||||
var folderName = CoolUtil.getFilename(char.substr(0, char.length-1));
|
||||
|
||||
list.push(new TextOption(folderName + " >", translate("acceptFolder"), function() {
|
||||
list.push(new TextOption(folderName, getID('acceptFolder'), ' >', () -> {
|
||||
var newModsList = Character.getList(isMods, true, char);
|
||||
var newList:Array<OptionType> = generateList(newModsList, isMods, folderPath + folderName + "/");
|
||||
optionsTree.add(new OptionsScreen(folderPath + folderName, translate("desc-folder", [folderPath + folderName + "/"]), newList));
|
||||
var newList:Array<FlxSprite> = generateList(newModsList, isMods, folderPath + folderName + "/");
|
||||
parent.addMenu(new EditorTreeMenuScreen(folderPath + folderName, translate('desc-folder', [folderPath + folderName + "/"]), newList));
|
||||
}));
|
||||
}
|
||||
else {
|
||||
list.push(new IconOption(char, getID('acceptCharacter'), Character.getIconFromCharName(folderPath + char, char), () -> {
|
||||
FlxG.switchState(new CharacterEditor(folderPath + char));
|
||||
}));
|
||||
} else {
|
||||
list.push(new IconOption(char, translate("acceptCharacter"), Character.getIconFromCharName(folderPath + char, char),
|
||||
function() {
|
||||
FlxG.switchState(new CharacterEditor(folderPath + char));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
list.insert(0, new NewOption(translate("newCharacter"), translate("newCharacterDesc"), function() {
|
||||
openSubState(new CharacterCreationScreen(createCharacter));
|
||||
}));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
var list = generateList(modsList, isMods);
|
||||
|
||||
main = new OptionsScreen(TU.translate("editor.character.name"), translate("desc"), list);
|
||||
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Character Editor"]);
|
||||
}
|
||||
|
||||
override function createPost() {
|
||||
super.createPost();
|
||||
|
||||
main.changeSelection(1);
|
||||
for (o in generateList(modsList, isMods)) add(o);
|
||||
}
|
||||
|
||||
public function createCharacter(name:String, imageSaveData:ImageSaveData, xml:Xml) {
|
||||
var characterAlreadyExists:Bool = modsList.contains(name);
|
||||
if (characterAlreadyExists) {
|
||||
openSubState(new UIWarningSubstate("Creating Character: Error!", "The character you are trying to create already exists, if you would like to override it delete the character first!", [
|
||||
{label: "Ok", color: 0xFFFF0000, onClick: function(t) {}}
|
||||
parent.openSubState(new UIWarningSubstate(TU.translate('characterCreationScreen.warning.char-exists-title'), TU.translate('characterCreationScreen.warning.char-exists-body'), [
|
||||
{label: TU.translate('editor.ok'), color: 0xFFFF0000, onClick: (t) -> {}}
|
||||
]));
|
||||
return;
|
||||
}
|
||||
@@ -88,11 +76,10 @@ class CharacterSelection extends EditorTreeMenu
|
||||
UIImageExplorer.saveFilesGlobal(imageSaveData, '${Paths.getAssetsRoot()}/images/characters');
|
||||
|
||||
// Add to Menu >:D
|
||||
var option:IconOption = new IconOption(name, "Press ACCEPT to edit this character.", Character.getIconFromCharName(name),
|
||||
function() {
|
||||
FlxG.switchState(new CharacterEditor(name));
|
||||
}
|
||||
);
|
||||
optionsTree.members[optionsTree.members.length-1].insert(1, option);
|
||||
var option:IconOption = new IconOption(name, getID('acceptCharacter'), Character.getIconFromCharName(name), () -> {
|
||||
FlxG.switchState(new CharacterEditor(name));
|
||||
});
|
||||
|
||||
insert(1, option);
|
||||
}
|
||||
}
|
||||
@@ -1,118 +1,83 @@
|
||||
package funkin.editors.charter;
|
||||
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.backend.chart.Chart;
|
||||
import funkin.backend.chart.ChartData.ChartMetaData;
|
||||
import funkin.backend.chart.ChartData;
|
||||
import funkin.backend.system.framerate.Framerate;
|
||||
import funkin.editors.EditorTreeMenu;
|
||||
import funkin.editors.charter.SongCreationScreen.SongCreationData;
|
||||
import funkin.editors.EditorTreeMenu;
|
||||
import funkin.menus.FreeplayState.FreeplaySonglist;
|
||||
import funkin.options.*;
|
||||
import funkin.options.type.*;
|
||||
import funkin.options.type.NewOption;
|
||||
import haxe.Json;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class CharterSelection extends EditorTreeMenu {
|
||||
public var freeplayList:FreeplaySonglist;
|
||||
public var curSong:ChartMetaData;
|
||||
public override function create() {
|
||||
bgType = "charter";
|
||||
|
||||
override function create() {
|
||||
super.create();
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Chart Editor"]);
|
||||
addMenu(new CharterSelectionScreen());
|
||||
bgType = 'charter';
|
||||
}
|
||||
}
|
||||
|
||||
Framerate.offset.y = 60;
|
||||
class CharterSelectionScreen extends EditorTreeMenuScreen {
|
||||
public var freeplayList:FreeplaySonglist;
|
||||
public var songList:Array<String> = [];
|
||||
public var curSong:ChartMetaData;
|
||||
|
||||
inline public function makeChartOption(d:String, name:String):TextOption {
|
||||
return new TextOption(d, getID('acceptDifficulty'), () -> FlxG.switchState(new Charter(name, d)));
|
||||
}
|
||||
|
||||
public function makeSongOption(s:ChartMetaData):IconOption {
|
||||
songList.push(s.name.toLowerCase());
|
||||
|
||||
var opt = new IconOption(s.name, getID('acceptSong'), s.icon, () -> {
|
||||
curSong = s;
|
||||
|
||||
var screen = new EditorTreeMenuScreen(s.name, getID('selectDifficulty'), [
|
||||
for (d in s.difficulties) if (d != '') makeChartOption(d, s.name)
|
||||
]);
|
||||
|
||||
#if sys
|
||||
screen.insert(0, new NewOption(getID('newDifficulty'), getID('newDifficultyDesc'), () -> {
|
||||
parent.openSubState(new ChartCreationScreen(saveChart));
|
||||
}));
|
||||
screen.curSelected = 1;
|
||||
#end
|
||||
|
||||
parent.addMenu(screen);
|
||||
});
|
||||
opt.suffix = ' >';
|
||||
opt.color = s.color.getDefault(FlxColor.WHITE);
|
||||
|
||||
return opt;
|
||||
}
|
||||
|
||||
public function new() {
|
||||
super('editor.chart.name', 'charterSelection.desc', 'charterSelection.', 'newSong', 'newSongDesc', () -> {
|
||||
parent.openSubState(new SongCreationScreen(saveSong));
|
||||
});
|
||||
freeplayList = FreeplaySonglist.get(false);
|
||||
|
||||
var list:Array<OptionType> = [
|
||||
for(s in freeplayList.songs) new EditorIconOption(s.name, TU.translate("charterSelection.acceptSong"), s.icon, function() {
|
||||
curSong = s;
|
||||
var list:Array<OptionType> = [
|
||||
for(d in s.difficulties) if (d != "")
|
||||
new TextOption(d, TU.translate("charterSelection.acceptDifficulty"), function() {
|
||||
FlxG.switchState(new Charter(s.name, d));
|
||||
})
|
||||
];
|
||||
#if sys
|
||||
var newDiff = TU.translate("charterSelection.newDifficulty");
|
||||
list.push(new NewOption(newDiff, newDiff, function() {
|
||||
FlxG.state.openSubState(new ChartCreationScreen(saveChart));
|
||||
}));
|
||||
#end
|
||||
optionsTree.add(new OptionsScreen(s.name, TU.translate("charterSelection.selectDifficulty"), list));
|
||||
}, s.color.getDefault(0xFFFFFFFF))
|
||||
];
|
||||
|
||||
#if sys
|
||||
var newSong = TU.translate("charterSelection.newSong");
|
||||
list.insert(0, new NewOption(newSong, newSong, function() {
|
||||
FlxG.state.openSubState(new SongCreationScreen(saveSong));
|
||||
}));
|
||||
#end
|
||||
|
||||
main = new OptionsScreen(TU.translate("editor.chart.name"), TU.translate("charterSelection.desc"), list);
|
||||
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Chart Editor"]);
|
||||
}
|
||||
|
||||
override function createPost() {
|
||||
super.createPost();
|
||||
|
||||
main.changeSelection(1);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
bg.colorTransform.redOffset = lerp(bg.colorTransform.redOffset, 0, 0.0625);
|
||||
bg.colorTransform.greenOffset = lerp(bg.colorTransform.greenOffset, 0, 0.0625);
|
||||
bg.colorTransform.blueOffset = lerp(bg.colorTransform.blueOffset, 0, 0.0625);
|
||||
bg.colorTransform.redMultiplier = lerp(bg.colorTransform.redMultiplier, 1, 0.0625);
|
||||
bg.colorTransform.greenMultiplier = lerp(bg.colorTransform.greenMultiplier, 1, 0.0625);
|
||||
bg.colorTransform.blueMultiplier = lerp(bg.colorTransform.blueMultiplier, 1, 0.0625);
|
||||
}
|
||||
|
||||
public override function onMenuChange() {
|
||||
super.onMenuChange();
|
||||
if (optionsTree.members.length > 1) { // selected a song
|
||||
if(main != null) {
|
||||
var opt = main.members[main.curSelected];
|
||||
if(opt is EditorIconOption) {
|
||||
var opt:EditorIconOption = cast opt;
|
||||
|
||||
// small flashbang
|
||||
var color = opt.flashColor;
|
||||
bg.colorTransform.redOffset = 0.25 * color.red;
|
||||
bg.colorTransform.greenOffset = 0.25 * color.green;
|
||||
bg.colorTransform.blueOffset = 0.25 * color.blue;
|
||||
bg.colorTransform.redMultiplier = FlxMath.lerp(1, color.redFloat, 0.25);
|
||||
bg.colorTransform.greenMultiplier = FlxMath.lerp(1, color.greenFloat, 0.25);
|
||||
bg.colorTransform.blueMultiplier = FlxMath.lerp(1, color.blueFloat, 0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i => s in freeplayList.songs) add(makeSongOption(s));
|
||||
}
|
||||
|
||||
#if sys
|
||||
public function saveSong(creation:SongCreationData, ?callback:String -> SongCreationData -> Void) {
|
||||
var songAlreadyExists:Bool = [for (s in freeplayList.songs) s.name.toLowerCase()].contains(creation.meta.name.toLowerCase());
|
||||
|
||||
var songAlreadyExists:Bool = songList.contains(creation.meta.name.toLowerCase());
|
||||
if (songAlreadyExists) {
|
||||
openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [
|
||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}},
|
||||
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [
|
||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
// Paths
|
||||
var songsDir:String = '${Paths.getAssetsRoot()}/songs/';
|
||||
var songFolder:String = '$songsDir${creation.meta.name}';
|
||||
var songFolder:String = '${Paths.getAssetsRoot()}/songs/${creation.meta.name}';
|
||||
|
||||
#if sys
|
||||
// Make Directories
|
||||
sys.FileSystem.createDirectory(songFolder);
|
||||
CoolUtil.addMissingFolders(songFolder);
|
||||
sys.FileSystem.createDirectory('$songFolder/song');
|
||||
sys.FileSystem.createDirectory('$songFolder/charts');
|
||||
|
||||
@@ -125,52 +90,30 @@ class CharterSelection extends EditorTreeMenu {
|
||||
if (creation.oppVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Opponent.${Flags.SOUND_EXT}', creation.oppVocals);
|
||||
#end
|
||||
|
||||
if (callback != null)
|
||||
callback(songFolder, creation);
|
||||
|
||||
var option = new EditorIconOption(creation.meta.name, TU.translate("charterSelection.acceptSong"), creation.meta.icon, function() {
|
||||
curSong = creation.meta;
|
||||
var list:Array<OptionType> = [
|
||||
for(d in creation.meta.difficulties)
|
||||
if (d != "") new TextOption(d, TU.translate("charterSelection.acceptDifficulty"), function() {
|
||||
FlxG.switchState(new Charter(creation.meta.name, d));
|
||||
})
|
||||
];
|
||||
var newDiff = TU.translate("charterSelection.newDifficulty");
|
||||
list.push(new NewOption(newDiff, newDiff, function() {
|
||||
FlxG.state.openSubState(new ChartCreationScreen(saveChart));
|
||||
}));
|
||||
optionsTree.insert(1, new OptionsScreen(creation.meta.name, TU.translate("charterSelection.selectDifficulty"), list));
|
||||
}, creation.meta.color.getDefault(0xFFFFFFFF));
|
||||
if (callback != null) callback(songFolder, creation);
|
||||
|
||||
// Add to List
|
||||
freeplayList.songs.insert(0, creation.meta);
|
||||
main.insert(1, option);
|
||||
insert(1, makeSongOption(creation.meta));
|
||||
}
|
||||
|
||||
public function saveChart(name:String, data:ChartData) {
|
||||
var difficultyAlreadyExists:Bool = curSong.difficulties.contains(name);
|
||||
|
||||
if (difficultyAlreadyExists) {
|
||||
openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [
|
||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}},
|
||||
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [
|
||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
// Paths
|
||||
var songFolder:String = '${Paths.getAssetsRoot()}/songs/${curSong.name}';
|
||||
|
||||
// Save Files
|
||||
CoolUtil.safeSaveFile('$songFolder/charts/${name}.json', Json.stringify(data, Flags.JSON_PRETTY_PRINT));
|
||||
|
||||
// Add to List
|
||||
// duplicated code, todo: fix this
|
||||
curSong.difficulties.push(name);
|
||||
var option = new TextOption(name, TU.translate("charterSelection.acceptDifficulty"), function() {
|
||||
FlxG.switchState(new Charter(curSong.name, name));
|
||||
});
|
||||
optionsTree.members[optionsTree.members.length-1].insert(optionsTree.members[optionsTree.members.length-1].length-1, option);
|
||||
parent.tree.last().insert(parent.tree.last().length - 1, makeChartOption(name, curSong.name));
|
||||
|
||||
// Add to Meta
|
||||
var meta = Json.parse(sys.io.File.getContent('$songFolder/meta.json'));
|
||||
|
||||
@@ -1,46 +1,47 @@
|
||||
package funkin.editors.stage;
|
||||
|
||||
import funkin.editors.stage.StageCreationScreen.StageCreationData;
|
||||
import funkin.editors.EditorTreeMenu;
|
||||
import funkin.game.Stage;
|
||||
import funkin.options.OptionsScreen;
|
||||
import funkin.options.type.NewOption;
|
||||
import funkin.options.type.OptionType;
|
||||
import funkin.options.type.TextOption;
|
||||
|
||||
class StageSelection extends EditorTreeMenu
|
||||
{
|
||||
using StringTools;
|
||||
|
||||
class StageSelection extends EditorTreeMenu {
|
||||
override function create() {
|
||||
super.create();
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Stage Editor"]);
|
||||
addMenu(new StageSelectionScreen());
|
||||
}
|
||||
}
|
||||
|
||||
class StageSelectionScreen extends EditorTreeMenuScreen {
|
||||
public var stages:Array<String> = [];
|
||||
|
||||
public override function create()
|
||||
{
|
||||
bgType = "charter";
|
||||
super.create();
|
||||
public function makeStageOption(stage:String):TextOption {
|
||||
return new TextOption(stage, getID('acceptStage'), () -> {
|
||||
FlxG.switchState(new StageEditor(stage));
|
||||
});
|
||||
}
|
||||
|
||||
public function new() {
|
||||
super('editor.stage.name', 'stageSelection.desc', 'stageSelection.', 'newStage', 'acceptNewStage', () -> {
|
||||
parent.openSubState(new StageCreationScreen(saveStage));
|
||||
});
|
||||
|
||||
var modsList:Array<String> = Stage.getList(true, true);
|
||||
|
||||
var list:Array<OptionType> = [
|
||||
for (stage in (modsList.length == 0 ? Stage.getList(false, true) : modsList)) {
|
||||
stages.push(stage);
|
||||
new TextOption(stage, TU.translate("stageSelection.acceptStage"),
|
||||
function() {
|
||||
FlxG.switchState(new StageEditor(stage));
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
list.insert(0, new NewOption(TU.translate("stageSelection.newStage"), TU.translate("stageSelection.acceptNewStage"), function() {
|
||||
FlxG.state.openSubState(new StageCreationScreen(saveStage));
|
||||
}));
|
||||
|
||||
main = new OptionsScreen(TU.translate("editor.stage.name"), TU.translate("stageSelection.desc"), list);
|
||||
|
||||
DiscordUtil.call("onEditorTreeLoaded", ["Stage Editor"]);
|
||||
for (stage in (modsList.length == 0 ? Stage.getList(false, true) : modsList)) {
|
||||
stages.push(stage.toLowerCase());
|
||||
add(makeStageOption(stage));
|
||||
}
|
||||
}
|
||||
|
||||
public function saveStage(creation:StageCreationData) {
|
||||
if ([for (s in stages) s.toLowerCase()].contains(creation.name.toLowerCase())) {
|
||||
openSubState(new UIWarningSubstate("Creating Stage: Error!", "The stage you are trying to create alreadly exists, if you would like to override it delete the stage first!", [
|
||||
{label: "Ok", color: 0xFFFF0000, onClick: function(t) {}}
|
||||
if (stages.contains(creation.name.toLowerCase())) {
|
||||
parent.openSubState(new UIWarningSubstate(TU.translate("stageCreationScreen.warnings.stage-exists-title"), TU.translate("stageCreationScreen.warnings.stage-exists-body"), [
|
||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
||||
]));
|
||||
return;
|
||||
}
|
||||
@@ -51,15 +52,7 @@ class StageSelection extends EditorTreeMenu
|
||||
#end
|
||||
|
||||
// Add to List
|
||||
var option = new TextOption(creation.name, TU.translate("stageSelection.acceptStage"), function() {
|
||||
FlxG.switchState(new StageEditor(creation.name));
|
||||
});
|
||||
optionsTree.members[optionsTree.members.length-1].insert(1, option);
|
||||
}
|
||||
|
||||
override function createPost() {
|
||||
super.createPost();
|
||||
|
||||
main.changeSelection(1);
|
||||
stages.push(creation.name.toLowerCase());
|
||||
parent.tree.last().insert(parent.tree.last().length - 1, makeStageOption(creation.name));
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import flixel.tweens.FlxTween;
|
||||
import funkin.backend.FunkinText;
|
||||
import funkin.backend.scripting.events.menu.MenuChangeEvent;
|
||||
import funkin.backend.scripting.events.NameEvent;
|
||||
//import funkin.menus.credits.CreditsMain;
|
||||
import funkin.menus.credits.CreditsMain;
|
||||
import funkin.options.OptionsMenu;
|
||||
import lime.app.Application;
|
||||
|
||||
@@ -168,7 +168,7 @@ class MainMenuState extends MusicBeatState
|
||||
{
|
||||
case 'story mode': FlxG.switchState(new StoryMenuState());
|
||||
case 'freeplay': FlxG.switchState(new FreeplayState());
|
||||
//case 'donate', 'credits': FlxG.switchState(new CreditsMain()); // kept donate for not breaking scripts, if you don't want donate to bring you to the credits menu, thats easy softcodable - Nex
|
||||
case 'donate', 'credits': FlxG.switchState(new CreditsMain()); // kept donate for not breaking scripts, if you don't want donate to bring you to the credits menu, thats easy softcodable - Nex
|
||||
case 'options': FlxG.switchState(new OptionsMenu());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package funkin.menus.credits;
|
||||
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.backend.system.github.GitHub;
|
||||
import funkin.backend.system.github.GitHubContributor.CreditsGitHubContributor;
|
||||
import funkin.options.PlayerSettings;
|
||||
import funkin.options.type.GithubIconOption;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class CreditsCodename extends funkin.options.TreeMenuScreen {
|
||||
public var error:Bool = false;
|
||||
public var totalContributions:Int = 0;
|
||||
public var contribFormats:Array<FlxTextFormatMarkerPair> = [];
|
||||
|
||||
public function new() {
|
||||
super("Codename Engine", "credits.allContributors");
|
||||
tryUpdating(true);
|
||||
}
|
||||
|
||||
// blame the secondary threads if the code has to look this bad - Nex
|
||||
private var _canReset:Bool = true;
|
||||
private var _downloadingSteps:Int = 0;
|
||||
override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
if (_downloadingSteps == 2) {
|
||||
_downloadingSteps = 0;
|
||||
_canReset = true;
|
||||
displayList();
|
||||
} else if (_downloadingSteps == 1) {
|
||||
_downloadingSteps = 0;
|
||||
_canReset = true;
|
||||
updateMenuDesc();
|
||||
}
|
||||
else if (_canReset && PlayerSettings.solo.controls.RESET) tryUpdating();
|
||||
}
|
||||
|
||||
public function tryUpdating(forceDisplaying:Bool = false) {
|
||||
updateMenuDesc(TU.translate("credits.downloadingList"));
|
||||
_canReset = false;
|
||||
Main.execAsync(() -> {
|
||||
if (checkUpdate() || forceDisplaying) _downloadingSteps = 2;
|
||||
else _downloadingSteps = 1;
|
||||
});
|
||||
}
|
||||
|
||||
public override function updateMenuDesc(?txt:String) {
|
||||
if (!_canReset) return;
|
||||
super.updateMenuDesc(txt);
|
||||
updateMarkup();
|
||||
}
|
||||
|
||||
public function updateMarkup() {
|
||||
if (parent == null) return;
|
||||
var text:String = parent.descLabel.text;
|
||||
parent.descLabel.text = "";
|
||||
parent.descLabel.applyMarkup(text, contribFormats = [
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(Flags.MAIN_DEVS_COLOR), '*'),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(FlxColor.interpolate(Flags.MIN_CONTRIBUTIONS_COLOR, Flags.MAIN_DEVS_COLOR, Options.contributors[curSelected].contributions / totalContributions)), '~')
|
||||
]);
|
||||
}
|
||||
|
||||
override function destroy() {
|
||||
super.destroy();
|
||||
for (frmt in contribFormats) parent.descLabel.removeFormat(frmt.format);
|
||||
}
|
||||
|
||||
public function checkUpdate():Bool {
|
||||
var curTime:Float = Date.now().getTime();
|
||||
if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits - Nex
|
||||
Options.lastUpdated = curTime;
|
||||
|
||||
error = false;
|
||||
var idk = GitHub.getContributors(Flags.REPO_OWNER, Flags.REPO_NAME, function(e) {
|
||||
error = true;
|
||||
var errMsg:String = 'Error while trying to download contributors list:\n${CoolUtil.removeIP(e.message)}';
|
||||
Logs.error(errMsg.replace('\n', ' '));
|
||||
funkin.backend.utils.NativeAPI.showMessageBox("Codename Engine Warning", errMsg, MSG_WARNING);
|
||||
});
|
||||
if(error) return false;
|
||||
if((idk is Array)) {
|
||||
var contributors:Array<CreditsGitHubContributor> = [];
|
||||
for(e in idk) contributors.push({
|
||||
login: e.login,
|
||||
avatar_url: e.avatar_url,
|
||||
html_url: e.html_url,
|
||||
id: e.id,
|
||||
contributions: e.contributions
|
||||
});
|
||||
Options.contributors = contributors;
|
||||
}
|
||||
Logs.verbose('[CreditsCodename] Contributors list Updated!');
|
||||
|
||||
var errorOnMain:Bool = false;
|
||||
var idk2 = GitHub.getOrganizationMembers(Flags.REPO_OWNER, function(e) {
|
||||
errorOnMain = true;
|
||||
var errMsg:String = 'Error while trying to download ${Flags.REPO_OWNER} members list:\n${CoolUtil.removeIP(e.message)}';
|
||||
Logs.error(errMsg.replace('\n', ' '));
|
||||
funkin.backend.utils.NativeAPI.showMessageBox("Codename Engine Warning", errMsg, MSG_WARNING);
|
||||
});
|
||||
if(!errorOnMain) {
|
||||
Options.mainDevs = [for(m in idk2) m.id];
|
||||
Logs.verbose('[CreditsCodename] Main Devs list Updated!');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function displayList() {
|
||||
//if (curSelected > Options.contributors.length - 1) changeSelection(-(curSelected - (Options.contributors.length - 1)));
|
||||
if (curSelected > Options.contributors.length - 1) curSelected = Options.contributors.length - 1;
|
||||
changeSelection(0, true);
|
||||
|
||||
while (members.length > 0) {
|
||||
members[0].destroy();
|
||||
remove(members[0], true);
|
||||
}
|
||||
|
||||
totalContributions = 0;
|
||||
for(c in Options.contributors) totalContributions += c.contributions;
|
||||
for(c in Options.contributors) {
|
||||
var text = TU.translate("credits.totalContributions", [c.contributions, totalContributions, FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)]);
|
||||
var opt:GithubIconOption = new GithubIconOption(c, text);
|
||||
if(Options.mainDevs.contains(c.id)) {
|
||||
opt.desc += TU.translate("credits.mainDev");
|
||||
@:privateAccess opt.__text.color = Flags.MAIN_DEVS_COLOR;
|
||||
}
|
||||
add(opt);
|
||||
}
|
||||
|
||||
updateMenuDesc();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package funkin.menus.credits;
|
||||
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.backend.assets.AssetSource;
|
||||
import funkin.backend.system.github.GitHubContributor.CreditsGitHubContributor;
|
||||
import funkin.options.TreeMenu;
|
||||
import funkin.options.TreeMenuScreen;
|
||||
import funkin.options.type.*;
|
||||
import haxe.xml.Access;
|
||||
|
||||
class CreditsMain extends TreeMenu {
|
||||
var bg:FlxSprite;
|
||||
var items:Array<OptionType> = [];
|
||||
|
||||
override function create() {
|
||||
super.create();
|
||||
|
||||
DiscordUtil.call("onMenuLoaded", ["Credits Menu"]);
|
||||
|
||||
add(bg = new FlxSprite().loadAnimatedGraphic(Paths.image('menus/menuBGBlue')));
|
||||
bg.antialiasing = true;
|
||||
bg.scrollFactor.set();
|
||||
updateBG();
|
||||
|
||||
var first = new TreeMenuScreen('credits.name', 'credits.madePossible');
|
||||
addMenu(first);
|
||||
|
||||
for (i in funkin.backend.assets.ModsFolder.getLoadedMods()) {
|
||||
var xmlPath = Paths.xml('config/credits/LIB_$i');
|
||||
|
||||
if (Paths.assetsTree.existsSpecific(xmlPath, "TEXT")) {
|
||||
var access:Access = null;
|
||||
try access = new Access(Xml.parse(Paths.assetsTree.getSpecificAsset(xmlPath, "TEXT")))
|
||||
catch(e) Logs.trace('[CreditsMain] Error while parsing credits.xml: ${Std.string(e)}', ERROR);
|
||||
if (access != null) for (c in parseCreditsFromXML(access)) first.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
first.add(new TextOption('Codename Engine', 'credits.selectCodename', ' >', () -> addMenu(new CreditsCodename())));
|
||||
first.add(new TextOption('Friday Night Funkin\'', 'credits.selectBase', ' >', () -> CoolUtil.openURL(Flags.URL_FNF_ITCH)));
|
||||
}
|
||||
|
||||
public function updateBG() {
|
||||
var scaleX:Float = FlxG.width / bg.width;
|
||||
var scaleY:Float = FlxG.height / bg.height;
|
||||
bg.scale.x = bg.scale.y = Math.max(scaleX, scaleY) * 1.15;
|
||||
bg.screenCenter();
|
||||
}
|
||||
|
||||
// XML STUFF
|
||||
public function parseCreditsFromXML(xml:Access, source:AssetSource = BOTH):Array<FlxSprite> {
|
||||
var credsMenus:Array<FlxSprite> = [];
|
||||
|
||||
for(node in xml.elements) {
|
||||
var desc = node.getAtt("desc").getDefault("No Description");
|
||||
|
||||
if (node.name == "github") {
|
||||
if (!node.has.user) {
|
||||
Logs.warn("A github node requires a user attribute.", "CreditsMain");
|
||||
continue;
|
||||
}
|
||||
|
||||
var username = node.getAtt("user");
|
||||
var user:CreditsGitHubContributor = { // Kind of forcing
|
||||
login: username,
|
||||
html_url: 'https://github.com/$username',
|
||||
avatar_url: 'https://github.com/$username.png'
|
||||
};
|
||||
var opt:GithubIconOption = new GithubIconOption(user, desc, null,
|
||||
node.has.customName ? node.att.customName : null,
|
||||
node.has.size ? Std.parseInt(node.att.size) : 96,
|
||||
node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
|
||||
);
|
||||
if (node.has.color)
|
||||
@:privateAccess opt.__text.color = FlxColor.fromString(node.att.color);
|
||||
credsMenus.push(opt);
|
||||
} else {
|
||||
if (!node.has.name) {
|
||||
Logs.warn("A credit node requires a name attribute.", "CreditsMain");
|
||||
continue;
|
||||
}
|
||||
var name = node.getAtt("name");
|
||||
|
||||
switch(node.name) {
|
||||
case "credit":
|
||||
var opt:PortraitOption = new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url),
|
||||
node.has.icon && Paths.assetsTree.existsSpecific(Paths.image('credits/${node.att.icon}'), "IMAGE", source) ?
|
||||
FlxG.bitmap.add(Paths.image('credits/${node.att.icon}')) : null, node.has.size ? Std.parseInt(node.att.size) : 96,
|
||||
node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
|
||||
);
|
||||
if (node.has.color)
|
||||
@:privateAccess opt.__text.color = FlxColor.fromString(node.att.color);
|
||||
credsMenus.push(opt);
|
||||
|
||||
case "menu":
|
||||
credsMenus.push(new TextOption(name, desc, ' >', () -> addMenu(new TreeMenuScreen(name, desc, parseCreditsFromXML(node, source)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return credsMenus;
|
||||
}
|
||||
}
|
||||
@@ -94,7 +94,7 @@ class OptionsMenu extends TreeMenu {
|
||||
var access:Access = null;
|
||||
try access = new Access(Xml.parse(Paths.assetsTree.getSpecificAsset(xmlPath, "TEXT")))
|
||||
catch(e) Logs.trace('Error while parsing options.xml: ${Std.string(e)}', ERROR);
|
||||
//if (access != null) for (o in parseOptionsFromXML(access)) main.add(o);
|
||||
if (access != null) for (o in parseOptionsFromXML(access)) tree.first().add(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,9 +120,8 @@ class OptionsMenu extends TreeMenu {
|
||||
}
|
||||
|
||||
// XML STUFF
|
||||
/*
|
||||
public function parseOptionsFromXML(xml:Access):Array<OptionType> {
|
||||
var options:Array<OptionType> = [];
|
||||
public function parseOptionsFromXML(xml:Access):Array<FlxSprite> {
|
||||
var options:Array<FlxSprite> = [];
|
||||
|
||||
for(node in xml.elements) {
|
||||
if (!node.has.name) {
|
||||
@@ -164,13 +163,10 @@ class OptionsMenu extends TreeMenu {
|
||||
options.push(new ArrayOption(name, desc, optionOptions, optionDisplayOptions, node.att.id, null, FlxG.save.data));
|
||||
|
||||
case "menu":
|
||||
options.push(new TextOption(name + " >", desc, function() {
|
||||
optionsTree.add(new TreeMenuScreen(name, desc, parseOptionsFromXML(node)));
|
||||
}));
|
||||
options.push(new TextOption(name, desc, ' >', () -> addMenu(new TreeMenuScreen(name, desc, parseOptionsFromXML(node)))));
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
// REMOVE THIS WHEN COMPLETE
|
||||
|
||||
package funkin.options;
|
||||
|
||||
import funkin.options.type.OptionType;
|
||||
|
||||
class OptionsScreen extends FlxTypedSpriteGroup<OptionType> {
|
||||
public static var optionHeight:Float = 120;
|
||||
|
||||
public var parent:OptionsTree;
|
||||
|
||||
public var curSelected:Int = 0;
|
||||
public var id:Int = 0;
|
||||
|
||||
private var __firstFrame:Bool = true;
|
||||
|
||||
public var name:String;
|
||||
public var desc:String;
|
||||
/**
|
||||
* The prefix to add to the translations ids.
|
||||
**/
|
||||
public var prefix:String = "";
|
||||
|
||||
private var rawName(default, set):String;
|
||||
private var rawDesc(default, set):String;
|
||||
|
||||
public inline function getNameID(name):String {
|
||||
return prefix + name + "-name";
|
||||
}
|
||||
public inline function getDescID(name):String {
|
||||
return prefix + name + "-desc";
|
||||
}
|
||||
|
||||
public function getName(name:String, ?args:Array<Dynamic>):String {
|
||||
return TU.translate(getNameID(name), args);
|
||||
}
|
||||
public function getDesc(name:String, ?args:Array<Dynamic>):String {
|
||||
return TU.translate(getDescID(name), args);
|
||||
}
|
||||
public function translate(name:String, ?args:Array<Dynamic>):String {
|
||||
return TU.translate(prefix + name, args);
|
||||
}
|
||||
|
||||
public function new(name:String, desc:String, ?prefix:String, ?options:Array<OptionType>) {
|
||||
super();
|
||||
rawName = name;
|
||||
rawDesc = desc;
|
||||
this.prefix = prefix != null ? prefix : "";
|
||||
if (options != null) for(o in options) add(o);
|
||||
}
|
||||
|
||||
function set_rawName(v:String) {
|
||||
rawName = v;
|
||||
this.name = TU.exists(rawName) ? TU.translate(rawName) : rawName;
|
||||
return v;
|
||||
}
|
||||
|
||||
function set_rawDesc(v:String) {
|
||||
rawDesc = v;
|
||||
this.desc = TU.exists(rawDesc) ? TU.translate(rawDesc) : rawDesc;
|
||||
return v;
|
||||
}
|
||||
|
||||
public function reloadStrings() {
|
||||
this.rawName = rawName;
|
||||
this.rawDesc = rawDesc;
|
||||
|
||||
for(o in members) {
|
||||
o.reloadStrings();
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
var controls = PlayerSettings.solo.controls;
|
||||
|
||||
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
|
||||
x = id * FlxG.width;
|
||||
for(k=>option in members) {
|
||||
if(option == null) continue;
|
||||
|
||||
var y:Float = ((FlxG.height - optionHeight) / 2) + ((k - curSelected) * optionHeight);
|
||||
|
||||
option.selected = false;
|
||||
option.y = __firstFrame ? y : CoolUtil.fpsLerp(option.y, y, 0.25);
|
||||
option.x = x + (-50 + (Math.abs(Math.cos((option.y + (optionHeight / 2) - (FlxG.camera.scroll.y + (FlxG.camera.height / 2))) / (FlxG.camera.height * 1.25) * Math.PI)) * 150));
|
||||
}
|
||||
if (__firstFrame) {
|
||||
__firstFrame = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (members.length > 0) {
|
||||
members[curSelected].selected = true;
|
||||
if (controls.ACCEPT || (FlxG.mouse.justReleased && Main.timeSinceFocus > 0.25)) {
|
||||
members[curSelected].select();
|
||||
onSelect(members[curSelected]);
|
||||
}
|
||||
if (controls.LEFT_P)
|
||||
members[curSelected].changeSelection(-1);
|
||||
if (controls.RIGHT_P)
|
||||
members[curSelected].changeSelection(1);
|
||||
}
|
||||
if (controls.BACK || FlxG.mouse.justReleasedRight)
|
||||
close();
|
||||
}
|
||||
|
||||
public function close() {
|
||||
onClose(this);
|
||||
}
|
||||
|
||||
public function changeSelection(sel:Int, force:Bool = false) {
|
||||
if (members.length <= 0 || (sel == 0 && !force)) return;
|
||||
|
||||
CoolUtil.playMenuSFX(SCROLL);
|
||||
curSelected = FlxMath.wrap(curSelected + sel, 0, members.length-1);
|
||||
members[curSelected].selected = true;
|
||||
updateMenuDesc();
|
||||
}
|
||||
|
||||
public function updateMenuDesc(?customTxt:String) {
|
||||
if (parent == null || parent.treeParent == null) return;
|
||||
parent.treeParent.updateDesc(customTxt != null ? customTxt : members[curSelected].desc);
|
||||
}
|
||||
|
||||
public dynamic function onClose(o:OptionsScreen) {}
|
||||
public dynamic function onSelect(o:OptionType) {
|
||||
if(o is funkin.options.type.RadioButton) {
|
||||
var orb:funkin.options.type.RadioButton = cast o;
|
||||
for(e in members) {
|
||||
if(e is funkin.options.type.RadioButton) {
|
||||
var rb:funkin.options.type.RadioButton = cast e;
|
||||
if(rb.forId == orb.forId && rb != o) {
|
||||
rb.checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
// REMOVE THIS WHEN COMPLETE
|
||||
|
||||
package funkin.options;
|
||||
|
||||
class OptionsTree extends FlxTypedGroup<OptionsScreen> {
|
||||
public var lastMenu:OptionsScreen;
|
||||
public var treeParent:TreeMenu;
|
||||
public var wasClosing:Bool = false;
|
||||
//public override function new() {
|
||||
// super();
|
||||
//}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
var last = members.last();
|
||||
if (last != null)
|
||||
last.update(elapsed);
|
||||
}
|
||||
|
||||
public function updateAll(elapsed:Float) {
|
||||
for (member in members) {
|
||||
if(member == null) continue;
|
||||
if(member.active && member.exists) {
|
||||
member.update(elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override function draw() {
|
||||
super.draw();
|
||||
if (lastMenu != null) { // manually draw lastMenu since it got removed from the members list
|
||||
lastMenu.draw();
|
||||
}
|
||||
}
|
||||
|
||||
public function reloadStrings() {
|
||||
for(o in members) {
|
||||
o.reloadStrings();
|
||||
}
|
||||
}
|
||||
|
||||
public override function add(m:OptionsScreen) {
|
||||
super.add(m);
|
||||
setup(m);
|
||||
clearLastMenu();
|
||||
wasClosing = false;
|
||||
onMenuChange();
|
||||
return m;
|
||||
}
|
||||
public override function insert(pos:Int, m:OptionsScreen) {
|
||||
var last = members.last();
|
||||
super.insert(pos, m);
|
||||
setup(m);
|
||||
if (last != members.last()) {
|
||||
wasClosing = false;
|
||||
onMenuChange();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
public function setup(m:OptionsScreen) {
|
||||
m.onClose = __subMenuClose;
|
||||
m.id = members.indexOf(m);
|
||||
m.parent = this;
|
||||
m.update(0);
|
||||
}
|
||||
|
||||
function __subMenuClose(m:OptionsScreen) {
|
||||
wasClosing = true;
|
||||
clearLastMenu();
|
||||
lastMenu = m;
|
||||
remove(m, true);
|
||||
onMenuChange();
|
||||
onMenuClose(m);
|
||||
}
|
||||
|
||||
public function clearLastMenu() {
|
||||
lastMenu = FlxDestroyUtil.destroy(lastMenu);
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
super.destroy();
|
||||
lastMenu = FlxDestroyUtil.destroy(lastMenu);
|
||||
}
|
||||
|
||||
public dynamic function onMenuChange() {
|
||||
|
||||
}
|
||||
|
||||
public dynamic function onMenuClose(m:OptionsScreen) {
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,6 @@ class TreeMenu extends UIState {
|
||||
public var descLabel:FunkinText;
|
||||
public var bgLabel:FlxSprite;
|
||||
|
||||
public var optionsTree:OptionsTree;
|
||||
|
||||
var menuChangeTween:FlxTween;
|
||||
var __drawer:TreeMenuDrawer;
|
||||
var __treeCreated:Bool = false;
|
||||
@@ -74,7 +72,9 @@ class TreeMenu extends UIState {
|
||||
add(bgLabel);
|
||||
add(titleLabel);
|
||||
add(descLabel);
|
||||
updateLabels();
|
||||
|
||||
FlxG.camera.scroll.x = -FlxG.width;
|
||||
menuChanged();
|
||||
|
||||
__treeCreated = true;
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package funkin.options.type;
|
||||
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class EditorIconOption extends IconOption {
|
||||
public var flashColor:FlxColor;
|
||||
|
||||
public function new(name:String, desc:String, icon:String, callback:Void->Void, flashColor:FlxColor = 0) {
|
||||
super(name, desc, icon, callback);
|
||||
|
||||
this.flashColor = flashColor;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ class GithubIconOption extends TextOption
|
||||
this.icon = new GithubUserIcon(user, size, waitUntilLoad);
|
||||
this.usePortrait = usePortrait;
|
||||
add(icon);
|
||||
__text.x = 100;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ class NewOption extends TextOption {
|
||||
|
||||
public function new(name:String, desc:String, callback:Void->Void) {
|
||||
super(name, desc, callback);
|
||||
itemHeight = 160;
|
||||
|
||||
__text.color = FlxColor.LIME;
|
||||
__text.x = 100;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package funkin.options.type;
|
||||
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.backend.system.Controls;
|
||||
import funkin.options.TreeMenu.ITreeOption;
|
||||
|
||||
@@ -19,6 +20,8 @@ class OptionType extends FlxSpriteGroup implements ITreeOption {
|
||||
|
||||
public var itemHeight:Float = 120;
|
||||
|
||||
public var editorFlashColor:FlxColor = FlxColor.WHITE;
|
||||
|
||||
public function new(text:String, desc:String) {
|
||||
super();
|
||||
rawText = text;
|
||||
|
||||
@@ -6,7 +6,7 @@ import flixel.effects.FlxFlicker;
|
||||
* Option type that has text.
|
||||
**/
|
||||
class TextOption extends OptionType {
|
||||
public var suffix:String;
|
||||
public var suffix(default, set):String;
|
||||
public var selectCallback:Void->Void;
|
||||
|
||||
var __text:Alphabet;
|
||||
@@ -15,6 +15,12 @@ class TextOption extends OptionType {
|
||||
return text = v;
|
||||
}
|
||||
|
||||
function set_suffix(v:String) {
|
||||
if (suffix == (suffix = v)) return v;
|
||||
__text.text = text + suffix;
|
||||
return v;
|
||||
}
|
||||
|
||||
public function new(text:String, desc:String, ?suffix:String = "", ?selectCallback:Void->Void = null) {
|
||||
this.suffix = suffix;
|
||||
this.selectCallback = selectCallback;
|
||||
|
||||
Reference in New Issue
Block a user