1 men, 2 pregnant FINISHED

WOHOO READY FOR THE TESTERSSS!!!

Co-Authored-By: Ne_Eo <NeeEoo@users.noreply.github.com>
This commit is contained in:
⍚~Nex
2024-10-04 16:55:32 +02:00
co-authored by Ne_Eo
parent 69a2f9f953
commit afdb0a182d
18 changed files with 301 additions and 73 deletions
+9 -2
View File
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<language>
<str id="optionsMenu.desc-missing">No Description</str>
<group name="OptionsMenu">
<str id="optionsMenu.header.title">Options Menu</str>
<str id="optionsMenu.header.desc">Select a category to continue.</str>
@@ -13,6 +15,9 @@
<str id="optionsTree.appearance-name">Appearance</str>
<str id="optionsTree.appearance-desc">Change Appearance options such as Flashing menus...</str>
<str id="optionsTree.language-name">Language</str>
<str id="optionsTree.language-desc">Change the language that the engine uses.</str>
<str id="optionsTree.miscellaneous-name">Miscellaneous</str>
<str id="optionsTree.miscellaneous-desc">Use this menu to reset save data or engine settings.</str>
@@ -65,10 +70,12 @@
<str id="camZoomOnBeat-desc">If unchecked, will stop the camera from zooming in every 4 beats</str>
</group>
<group name="MiscOptions" prefix="MiscOptions.">
<group name="LanguageOptions" prefix="LanguageOptions.">
<str id="language-name">Language</str>
<str id="language-desc">The language that the engine currently uses (the default one is {0}).</str>
<str id="language-desc">Language by {0} (Version: {1})</str>
</group>
<group name="MiscOptions" prefix="MiscOptions.">
<str id="forceCrash-name">Force Crash</str>
<str id="forceCrash-desc">Select this option to force a crash.</str>
+2
View File
@@ -2,6 +2,8 @@ name="English"
credits="Codename Engine Devs"
version="0.0.1"
; Moving these in the wiki when releasing
; Shows missing ID:s as {id} and prints in the console Missing Translation IDs: id
; otherwhise uses the other languages (based on the chosen order) for the missing translations
; NOTE: it is recommended to use this feature for debug only, but do as you wish
showMissingIds="true"
+3 -1
View File
@@ -1,7 +1,9 @@
name="Italian"
name="Italiano"
credits="Nex_isDumb"
version="0.0.1"
; Moving these in the wiki when releasing
; Shows missing ID:s as {id} and prints in the console Missing Translation IDs: id
; otherwhise uses the other languages (based on the chosen order) for the missing translations
; NOTE: it is recommended to use this feature for debug only, but do as you wish
showMissingIds="false"
+15 -9
View File
@@ -29,7 +29,7 @@ final class TranslationUtil
* It is filled with the default language.
*
* This is filled in if the current language is not the same as the default language.
* Its used when showMissingIds is false.
* Its used when showMissingIds in the config is false (or is not present).
*
* It'll never be `null`.
**/
@@ -63,8 +63,6 @@ final class TranslationUtil
*/
public static var foundLanguages:Array<String> = [];
public static var showMissingIds:Bool = false;
// Private
private static inline var LANG_FOLDER:String = "languages";
private static var langConfigs:Map<String, IniMap> = [];
@@ -116,8 +114,7 @@ final class TranslationUtil
config = getConfig(name);
stringMap = loadLanguage(name);
showMissingIds = config.get("showMissingIds").getDefault("false") == "true";
alternativeStringMap = name == Flags.DEFAULT_LANGUAGE || config.get("showMissingIds").getDefault("false") == "true" ? [] : loadLanguage(Flags.DEFAULT_LANGUAGE);
#end
}
@@ -135,13 +132,18 @@ final class TranslationUtil
public static inline function translateDiff(?id:String, ?params:Array<Dynamic>):String
return get("diff." + id.toLowerCase(), params, id);
public static inline function exists(id:String):Bool
return #if TRANSLATIONS_SUPPORT stringMap.exists(id) #else false #end;
public static function exists(id:String):Bool {
#if TRANSLATIONS_SUPPORT
for (map in [stringMap, alternativeStringMap]) if (map.exists(id)) return true;
#end
return false;
}
public static function getRaw(id:String, ?def:String):IFormatInfo
{
#if TRANSLATIONS_SUPPORT
if (stringMap.exists(id)) return stringMap.get(id);
for (map in [stringMap, alternativeStringMap]) if (map.exists(id))
return map.get(id);
#end
if(def != null)
@@ -314,6 +316,10 @@ final class TranslationUtil
return langConfigs.exists(lang) ? langConfigs.get(lang) : getDefaultConfig(lang);
}
public static inline function isShowingMissingIds():Bool {
return alternativeStringMap != [];
}
public static inline function translationsMain(key:String):String
return '$LANG_FOLDER/$key';
@@ -350,7 +356,7 @@ final class TranslationUtil
return Options.language == Flags.DEFAULT_LANGUAGE;
@:noCompletion private static function get_isLanguageLoaded():Bool
return Lambda.count(stringMap) > 0;
return Lambda.count(stringMap) > 0 || (isShowingMissingIds() && Lambda.count(alternativeStringMap) > 0);
}
@:structInit
+4
View File
@@ -209,6 +209,10 @@ class Alphabet extends FlxSpriteGroup
addText();
}
}
override function draw() {
super.draw();
}
}
class AlphaCharacter extends FlxSprite
+6 -1
View File
@@ -127,7 +127,12 @@ class Options
if (!__eventAdded) {
Lib.application.onExit.add(function(i:Int) {
trace("Saving settings...");
Logs.traceColored([
Logs.getPrefix("Options"),
Logs.logText("Saving "),
Logs.logText("settings", GREEN),
Logs.logText("...")
], VERBOSE);
save();
});
__eventAdded = true;
+31 -14
View File
@@ -13,7 +13,9 @@ class OptionsMenu extends TreeMenu {
name: 'optionsTree.controls-name',
desc: 'optionsTree.controls-desc',
state: null,
substate: funkin.options.keybinds.KeybindsOptions
substate: (name:String, desc:String) -> {
return new funkin.options.keybinds.KeybindsOptions();
}
},
{
name: 'optionsTree.gameplay-name',
@@ -27,6 +29,14 @@ class OptionsMenu extends TreeMenu {
suffix: " >",
state: AppearanceOptions
},
#if TRANSLATIONS_SUPPORT
{
name: 'optionsTree.language-name',
desc: 'optionsTree.language-desc',
suffix: " >",
state: LanguageOptions
},
#end
{
name: 'optionsTree.miscellaneous-name',
desc: 'optionsTree.miscellaneous-desc',
@@ -51,27 +61,27 @@ class OptionsMenu extends TreeMenu {
bg.antialiasing = true;
add(bg);
main = new OptionsScreen(TU.translate("optionsMenu.header.title"), TU.translate("optionsMenu.header.desc"), [for(o in mainOptions) {
var name = o.name;
var desc = o.desc;
if(TU.exists(name)) name = TU.translate(name);
if(TU.exists(desc)) desc = TU.translate(desc);
var visualName = name;
if (o.suffix != null) visualName += o.suffix;
new TextOption(visualName, desc, function() {
main = new OptionsScreen("optionsMenu.header.title", "optionsMenu.header.desc", [for(o in mainOptions) {
new TextOption(o.name, o.desc, o.suffix, function() {
if (o.substate != null) {
persistentUpdate = false;
persistentDraw = true;
if (o.substate is MusicBeatSubstate) {
openSubState(o.substate);
} else {
openSubState(Type.createInstance(o.substate, [name, desc]));
} else if(Reflect.isFunction(o.substate)) {
var substate:(name:String, desc:String) -> MusicBeatSubstate = o.substate;
openSubState(substate(o.name, o.desc));
} else { // o.substate is Class<OptionsScreen>
openSubState(Type.createInstance(o.substate, [o.name, o.desc]));
}
} else {
if (o.state is OptionsScreen) {
optionsTree.add(o.state);
} else {
optionsTree.add(Type.createInstance(o.state, [name, desc]));
} else if(Reflect.isFunction(o.state)) {
var state:(name:String, desc:String) -> OptionsScreen = o.state;
optionsTree.add(state(o.name, o.desc));
} else { // o.state is Class<OptionsScreen>
optionsTree.add(Type.createInstance(o.state, [o.name, o.desc]));
}
}
});
@@ -92,7 +102,14 @@ class OptionsMenu extends TreeMenu {
main.add(o);
}
}
}
public function reloadStrings() {
for(o in main.members) {
o.reloadStrings();
}
optionsTree.reloadStrings();
reloadLabels();
}
public override function exit() {
@@ -113,7 +130,7 @@ class OptionsMenu extends TreeMenu {
continue;
}
var name = node.getAtt("name");
var desc = node.getAtt("desc").getDefault("No Description");
var desc = node.getAtt("desc").getDefault("optionsMenu.desc-missing");
switch(node.name) {
case "checkbox":
+39 -5
View File
@@ -14,13 +14,26 @@ class OptionsScreen extends FlxTypedSpriteGroup<OptionType> {
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(prefix + name + "-name", args);
return TU.translate(getNameID(name), args);
}
public function getDesc(name:String, ?args:Array<Dynamic>):String {
return TU.translate(prefix + name + "-desc", args);
return TU.translate(getDescID(name), args);
}
public function translate(name:String, ?args:Array<Dynamic>):String {
return TU.translate(prefix + name, args);
@@ -28,12 +41,33 @@ class OptionsScreen extends FlxTypedSpriteGroup<OptionType> {
public function new(name:String, desc:String, ?prefix:String, ?options:Array<OptionType>) {
super();
this.name = name;
this.desc = desc;
if (prefix != null) this.prefix = prefix;
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);
+21 -2
View File
@@ -3,6 +3,7 @@ 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();
//}
@@ -13,18 +14,33 @@ class OptionsTree extends FlxTypedGroup<OptionsScreen> {
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) {
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;
}
@@ -32,8 +48,10 @@ class OptionsTree extends FlxTypedGroup<OptionsScreen> {
var last = members.last();
super.insert(pos, m);
setup(m);
if (last != members.last())
if (last != members.last()) {
wasClosing = false;
onMenuChange();
}
return m;
}
@@ -45,6 +63,7 @@ class OptionsTree extends FlxTypedGroup<OptionsScreen> {
}
function __subMenuClose(m:OptionsScreen) {
wasClosing = true;
clearLastMenu();
lastMenu = m;
remove(m, true);
+36 -14
View File
@@ -3,6 +3,7 @@ package funkin.options;
import flixel.FlxState;
import flixel.tweens.FlxTween;
import flixel.util.typeLimit.OneOfTwo;
import flixel.util.typeLimit.OneOfThree;
import funkin.backend.FunkinText;
import funkin.editors.ui.UIState;
import funkin.menus.MainMenuState;
@@ -64,21 +65,47 @@ class TreeMenu extends UIState {
if (menuChangeTween != null)
menuChangeTween.cancel();
// i hate this code - Nex
// we need to rewrite OptionsTree to be more sane
var current = null;
var last = null;
var wasClosing = optionsTree.wasClosing;
current = optionsTree.members.last();
if (wasClosing) {
last = optionsTree.lastMenu;
} else if (optionsTree.members.length > 1) {
last = optionsTree.members[optionsTree.members.length - 2]; // previous
}
if (current != null)
current.visible = true;
menuChangeTween = FlxTween.tween(FlxG.camera.scroll, {x: FlxG.width * Math.max(0, (optionsTree.members.length-1))}, 1.5, {ease: menuTransitionEase, onComplete: function(t) {
optionsTree.clearLastMenu();
if (!wasClosing && last != null) // only hide if they are opening a menu
last.visible = false;
menuChangeTween = null;
}});
var t = "";
for(o in optionsTree.members)
t += '${o.name} > ';
pathLabel.text = t;
var idk:OptionsScreen = optionsTree.members.last();
if (idk.members.length > 0) updateDesc(idk.members[idk.curSelected].desc);
reloadLabels();
}
}
public function onMenuClose(m:OptionsScreen) {
CoolUtil.playMenuSFX(CANCEL);
}
public function reloadLabels() {
var t = "";
for(o in optionsTree.members)
t += '${o.name} > ';
pathLabel.text = t;
var idk:OptionsScreen = optionsTree.members.last();
if (idk.members.length > 0) updateDesc(idk.members[idk.curSelected].desc);
}
public function updateDesc(moreTxt:String = '') {
pathDesc.text = optionsTree.members.last().desc;
if (moreTxt != null && moreTxt.length > 0) pathDesc.text += '\n' + moreTxt;
@@ -91,14 +118,9 @@ class TreeMenu extends UIState {
lastState = null;
}
public function onMenuClose(m:OptionsScreen) {
CoolUtil.playMenuSFX(CANCEL);
}
var menuChangeTween:FlxTween;
public override function update(elapsed:Float) {
super.update(elapsed);
Framerate.offset.y = pathBG.height;
// in case path gets so long it goes offscreen
@@ -112,8 +134,8 @@ class TreeMenu extends UIState {
typedef OptionCategory = {
var name:String;
var desc:String;
var state:OneOfTwo<OptionsScreen, Class<OptionsScreen>>;
var ?substate:OneOfTwo<MusicBeatSubstate, Class<MusicBeatSubstate>>;
var state:OneOfThree<OptionsScreen, Class<OptionsScreen>, (name:String, desc:String) -> OptionsScreen>;
var ?substate:OneOfThree<MusicBeatSubstate, Class<MusicBeatSubstate>, (name:String, desc:String) -> MusicBeatSubstate>;
var ?suffix:String;
}
@@ -0,0 +1,60 @@
package funkin.options.categories;
class LanguageBox extends Checkbox {
public var langID:String;
public function new(name:String, langID:String) {
this.langID = langID;
super(name, "LanguageOptions.language-desc", null, null);
}
override function reloadStrings() {
super.reloadStrings();
}
override function set_rawDesc(v:String) {
rawDesc = v;
var config = TU.getConfig(langID);
this.desc = TU.exists(rawDesc) ? TU.translate(
rawDesc, [config["credits"], config["version"]]
) : rawDesc;
return v;
}
override function update(elapsed:Float) {
var lastChecked = checked;
checked = langID == TU.curLanguage;
if(lastChecked != checked)
checkbox.animation.play("checking", true, !checked);
super.update(elapsed);
}
override function onSelect() {
checked = !checked;
if(checked) {
TranslationUtil.setLanguage(langID);
if(FlxG.state is OptionsMenu) {
var menu:OptionsMenu = cast FlxG.state;
menu.reloadStrings();
trace("Reloading strings");
}
}
checkbox.animation.play("checking", true, !checked);
}
}
class LanguageOptions extends OptionsScreen {
public override function new(title:String, desc:String) {
super(title, desc, "LanguageOptions.");
var langArray:Array<String> = TranslationUtil.foundLanguages;
for(lang in langArray) {
var split = lang.split("/");
var langId = split.first();
var langName = split.last();
var checkbox = new LanguageBox(langName, langId);
add(checkbox);
}
}
}
@@ -5,26 +5,6 @@ class MiscOptions extends OptionsScreen {
public override function new(title:String, desc:String) {
super(title, desc, "MiscOptions.");
{ // Language Option
var lanArray:Array<String> = TranslationUtil.foundLanguages;
// TODO: add credits based on the config file
add(new ArrayOption(
getName("language"),
getDesc("language", [Flags.DEFAULT_LANGUAGE]),
[for(lan in lanArray) lan.split("/").first()],
[for(lan in lanArray) lan.split("/").last()],
"language",
function(path:String) {
TranslationUtil.setLanguage(path);
parent.remove(this);
// Reload the current screen
// todo add parent.reload();
this.clear();
parent.add(new MiscOptions(title, desc));
}));
}
add(new TextOption(
getName("forceCrash"),
getDesc("forceCrash"),
+15
View File
@@ -15,6 +15,8 @@ class ArrayOption extends OptionType {
public var parent:Dynamic;
private var rawText(default, set):String;
public var text(get, set):String;
private function get_text() {return __text.text;}
private function set_text(v:String) {return __text.text = v;}
@@ -37,6 +39,19 @@ class ArrayOption extends OptionType {
add(__text = new Alphabet(100, 20, text, true));
add(__selectiontext = new Alphabet(__text.width + 120, -30, formatTextOption(), false));
rawText = text;
}
override function reloadStrings() {
super.reloadStrings();
this.rawText = rawText;
}
function set_rawText(v:String) {
rawText = v;
__text.text = TU.exists(rawText) ? TU.translate(rawText) : rawText;
return v;
}
public override function draw() {
+7 -2
View File
@@ -42,7 +42,9 @@ class Checkbox extends TextOption {
baseCheckboxOffset.set(checkbox.offset.x, checkbox.offset.y);
this.optionName = optionName;
checked = Reflect.field(parent, optionName);
if(optionName != null) {
checked = Reflect.field(parent, optionName);
}
}
public override function update(elapsed:Float) {
@@ -58,7 +60,10 @@ class Checkbox extends TextOption {
}
public override function onSelect() {
Reflect.setField(parent, optionName, checked = !checked);
checked = !checked;
if(optionName != null) {
Reflect.setField(parent, optionName, checked);
}
checkbox.animation.play("checking", true, !checked);
}
+15
View File
@@ -18,6 +18,8 @@ class NumOption extends OptionType {
public var parent:Dynamic;
private var rawText(default, set):String;
public var text(get, set):String;
private function get_text() {return __text.text;}
private function set_text(v:String) {return __text.text = v;}
@@ -39,6 +41,19 @@ class NumOption extends OptionType {
add(__text = new Alphabet(100, 20, text, true));
add(__number = new Alphabet(__text.width + 120, -30, ': $currentSelection', false));
rawText = text;
}
override function reloadStrings() {
super.reloadStrings();
this.rawText = rawText;
}
function set_rawText(v:String) {
rawText = v;
__text.text = TU.exists(rawText) ? TU.translate(rawText) : rawText;
return v;
}
public override function onChangeSelection(change:Float):Void
+12 -1
View File
@@ -7,10 +7,21 @@ class OptionType extends FlxSpriteGroup {
public var controls(get, null):Controls;
public var selected:Bool = false;
public var desc:String;
public var rawDesc(default, set):String;
public function new(desc:String) {
super();
this.desc = desc;
rawDesc = desc;
}
function set_rawDesc(v:String) {
rawDesc = v;
this.desc = TU.exists(rawDesc) ? TU.translate(rawDesc) : rawDesc;
return v;
}
public function reloadStrings() {
this.rawDesc = rawDesc;
}
private function get_controls() {return PlayerSettings.solo.controls;}
+20 -1
View File
@@ -6,15 +6,34 @@ class TextOption extends OptionType {
public var selectCallback:Void->Void;
private var __text:Alphabet;
private var rawText(default, set):String;
public var text(get, set):String;
private function get_text() {return __text.text;}
private function set_text(v:String) {return __text.text = v;}
public function new(text:String, desc:String, selectCallback:Void->Void) {
/**
* If you change this afterwards you will need to call `reloadStrings()`, or manually set rawText to rawText.
**/
public var suffix:String;
public function new(text:String, desc:String, ?suffix:String = "", ?selectCallback:Void->Void = null) {
super(desc);
this.selectCallback = selectCallback;
add(__text = new Alphabet(100, 20, text, true));
this.suffix = suffix;
rawText = text;
}
override function reloadStrings() {
super.reloadStrings();
this.rawText = rawText;
}
function set_rawText(v:String) {
rawText = v;
__text.text = (TU.exists(rawText) ? TU.translate(rawText) : rawText) + suffix;
return v;
}
public override function draw() {
+6 -1
View File
@@ -32,7 +32,12 @@ class FunkinSave {
if (!__eventAdded) {
Lib.application.onExit.add(function(i:Int) {
trace("Saving savedata...");
Logs.traceColored([
Logs.getPrefix("FunkinSave"),
Logs.logText("Saving "),
Logs.logText("savedata", GREEN),
Logs.logText("...")
], VERBOSE);
flush();
});
__eventAdded = true;