custom options????

This commit is contained in:
Yoshman29
2023-03-13 21:46:25 +01:00
parent 9cd0742f53
commit 5e41414249
11 changed files with 300 additions and 92 deletions
+96
View File
@@ -0,0 +1,96 @@
<!DOCTYPE codename-mod-options>
<!-- NOT WORKING YET -->
<menu name="Mod Options" desc="Modify mod options here">
<checkbox id="levelOfIdk" name="Level of idk" />
<choice id="levelOfChoice" name="Level of choice">
<value name="Disabled" value="disabled" />
<value name="This Only" value="thisonly" />
<value name="All" value="all" />
</choice>
<menu name="Submenu" desc="Submenu test">
<checkbox id="levelOfIdk2" name="Level of idk" />
<choice id="levelOfChoice" name="Level of choice">
<value name="Disabled" value="disabled" />
<value name="This Only" value="thisonly" />
<value name="All" value="all" />
</choice>
</menu>
</menu>
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
<menu name="Mod Options" desc="Modify mod options here" />
+1 -1
View File
@@ -1 +1 @@
2474
2481
+68 -82
View File
@@ -1,15 +1,15 @@
package funkin.options;
import funkin.options.type.Checkbox;
import haxe.xml.Access;
import flixel.tweens.FlxTween;
import funkin.options.OptionsScreen;
import funkin.menus.MainMenuState;
import funkin.options.type.TextOption;
import flixel.util.typeLimit.OneOfTwo;
import funkin.options.type.OptionType;
import funkin.options.type.*;
import funkin.options.categories.*;
import funkin.options.TreeMenu;
class OptionsMenu extends MusicBeatState {
class OptionsMenu extends TreeMenu {
public static var mainOptions:Array<OptionCategory> = [
{
name: 'Controls',
@@ -38,39 +38,10 @@ class OptionsMenu extends MusicBeatState {
state: DebugOptions
}
];
public var options:Array<OptionTypeDef>;
public var optionsTree:OptionsTree;
public function new(?options:Array<OptionTypeDef>) {
super();
}
public override function create() {
super.create();
var optionSprites:Array<OptionType> = [];
if (options == null) {
optionSprites = [for(o in mainOptions) new TextOption(o.name, o.desc, function() {
if (o.substate != null) {
persistentUpdate = false;
persistentDraw = true;
if (o.substate is MusicBeatSubstate) {
openSubState(o.substate);
} else {
openSubState(Type.createInstance(o.substate, []));
}
} else {
if (o.state is OptionsScreen) {
optionsTree.add(o.state);
} else {
optionsTree.add(Type.createInstance(o.state, []));
}
}
})];
} else {
optionSprites = [for(o in options) Type.createInstance(o.type, o.args)];
}
var bg:FlxSprite = new FlxSprite(-80).loadAnimatedGraphic(Paths.image('menus/menuBGBlue'));
// bg.scrollFactor.set();
bg.scale.set(1.15, 1.15);
@@ -80,61 +51,76 @@ class OptionsMenu extends MusicBeatState {
bg.antialiasing = true;
add(bg);
optionsTree = new OptionsTree();
optionsTree.onMenuChange = onMenuChange;
optionsTree.onMenuClose = onMenuClose;
var mainOptionScreen:OptionsScreen = new OptionsScreen();
for(o in optionSprites)
mainOptionScreen.add(o);
optionsTree.add(mainOptionScreen);
add(optionsTree);
FlxG.camera.scroll.set(-FlxG.width, 0);
}
public function onMenuChange() {
if (optionsTree.members.length <= 0) {
exit();
} else {
if (menuChangeTween != null) {
menuChangeTween.cancel();
main = new OptionsScreen("Options", "Select a category to continue.", [for(o in mainOptions) new TextOption(o.name, o.desc, function() {
if (o.substate != null) {
persistentUpdate = false;
persistentDraw = true;
if (o.substate is MusicBeatSubstate) {
openSubState(o.substate);
} else {
openSubState(Type.createInstance(o.substate, []));
}
} else {
if (o.state is OptionsScreen) {
optionsTree.add(o.state);
} else {
optionsTree.add(Type.createInstance(o.state, []));
}
}
})]);
var xmlPath = Paths.xml("config/options");
for(source in [funkin.system.AssetsLibraryList.AssetSource.SOURCE, funkin.system.AssetsLibraryList.AssetSource.MODS]) {
if (Paths.assetsTree.existsSpecific(xmlPath, "TEXT", source)) {
var access:Access = null;
try {
access = new Access(Xml.parse(Paths.assetsTree.getSpecificAsset(xmlPath, "TEXT", source)));
} catch(e) {
Logs.trace('Error while parsing options.xml: ${Std.string(e)}', ERROR);
}
if (access != null)
for(o in parseOptionsFromXML(access))
main.add(o);
}
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();
menuChangeTween = null;
}});
// TODO: update top info
}
}
public function exit() {
public override function exit() {
Options.save();
Options.applySettings();
FlxG.switchState(new MainMenuState());
super.exit();
}
public function onMenuClose(m:OptionsScreen) {
CoolUtil.playMenuSFX(CANCEL);
/**
* XML STUFF
*/
public function parseOptionsFromXML(xml:Access):Array<OptionType> {
var options:Array<OptionType> = [];
for(node in xml.elements) {
if (!node.has.name) {
Logs.trace("An option node requires a name attribute.", WARNING);
continue;
}
var name = node.getAtt("name");
var desc = node.getAtt("desc").getDefault("No Description");
switch(node.name) {
case "checkbox":
if (!node.has.id) {
Logs.trace("A checkbox option requires an \"id\" for option saving.", WARNING);
continue;
}
options.push(new Checkbox(name, desc, node.att.id, FlxG.save.data));
case "menu":
options.push(new TextOption(name, desc, function() {
optionsTree.add(new OptionsScreen(name, desc, parseOptionsFromXML(node)));
}));
}
}
return options;
}
var menuChangeTween:FlxTween;
public override function update(elapsed:Float) {
super.update(elapsed);
}
public static inline function menuTransitionEase(e:Float)
return FlxEase.quintInOut(FlxEase.cubeOut(e));
}
typedef OptionCategory = {
var name:String;
var desc:String;
var state:OneOfTwo<OptionsScreen, Class<OptionsScreen>>;
var ?substate:OneOfTwo<MusicBeatSubstate, Class<MusicBeatSubstate>>;
}
typedef OptionTypeDef = {
var type:Class<OptionType>;
var args:Array<Dynamic>;
}
+7 -2
View File
@@ -12,9 +12,14 @@ class OptionsScreen extends FlxTypedSpriteGroup<OptionType> {
private var __firstFrame:Bool = true;
public function new() {
public var name:String;
public var desc:String;
public function new(name:String, desc:String, ?options:Array<OptionType>) {
super();
// EXTEND then add options
this.name = name;
this.desc = desc;
if (options != null) for(o in options) add(o);
}
public override function update(elapsed:Float) {
+6
View File
@@ -1,5 +1,6 @@
package funkin.options;
import flixel.util.FlxDestroyUtil;
class OptionsTree extends FlxTypedGroup<OptionsScreen> {
public var lastMenu:OptionsScreen;
public override function new() {
@@ -59,6 +60,11 @@ class OptionsTree extends FlxTypedGroup<OptionsScreen> {
}
}
public override function destroy() {
super.destroy();
lastMenu = FlxDestroyUtil.destroy(lastMenu);
}
public dynamic function onMenuChange() {
}
+108
View File
@@ -0,0 +1,108 @@
package funkin.options;
import funkin.ui.FunkinText;
import flixel.tweens.FlxTween;
import funkin.menus.MainMenuState;
import funkin.options.type.TextOption;
import flixel.util.typeLimit.OneOfTwo;
import funkin.options.type.OptionType;
import funkin.options.categories.*;
class TreeMenu extends MusicBeatState {
public var main:OptionsScreen;
public var optionsTree:OptionsTree;
public var pathLabel:FunkinText;
public var pathDesc:FunkinText;
public var pathBG:FlxSprite;
public function new() {
super();
}
public override function createPost() {
if (main == null) throw "\"main\" variable has not been set in extended class!";
FlxG.camera.scroll.set(-FlxG.width, 0);
pathLabel = new FunkinText(4, 4, FlxG.width - 8, "> Tree Menu", 32, false);
pathLabel.scrollFactor.set();
pathDesc = new FunkinText(4, pathLabel.y + pathLabel.height + 2, FlxG.width - 8, "Current Tree Menu Description", 16, false);
pathDesc.scrollFactor.set();
pathBG = new FlxSprite().makeGraphic(1, 1, 0xFF000000);
pathBG.scale.set(FlxG.width, pathDesc.y + pathDesc.height + 2);
pathBG.updateHitbox();
pathBG.alpha = 0.25;
pathBG.scrollFactor.set();
optionsTree = new OptionsTree();
optionsTree.onMenuChange = onMenuChange;
optionsTree.onMenuClose = onMenuClose;
optionsTree.add(main);
add(optionsTree);
add(pathBG);
add(pathLabel);
add(pathDesc);
super.createPost();
}
public function onMenuChange() {
if (optionsTree.members.length <= 0) {
exit();
} else {
if (menuChangeTween != null)
menuChangeTween.cancel();
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();
menuChangeTween = null;
}});
var t = "";
for(o in optionsTree.members)
t += '${o.name} > ';
pathLabel.text = t;
pathDesc.text = optionsTree.members.last().desc;
pathBG.scale.set(FlxG.width, pathDesc.y + pathDesc.height + 2);
pathBG.updateHitbox();
}
}
public function exit() {
FlxG.switchState(new MainMenuState());
}
public function onMenuClose(m:OptionsScreen) {
CoolUtil.playMenuSFX(CANCEL);
}
var menuChangeTween:FlxTween;
public override function update(elapsed:Float) {
super.update(elapsed);
// in case path gets so long it goes offscreen
pathLabel.x = lerp(pathLabel.x, Math.max(0, FlxG.width - 4 - pathLabel.width), 0.125);
}
public static inline function menuTransitionEase(e:Float)
return FlxEase.quintInOut(FlxEase.cubeOut(e));
}
typedef OptionCategory = {
var name:String;
var desc:String;
var state:OneOfTwo<OptionsScreen, Class<OptionsScreen>>;
var ?substate:OneOfTwo<MusicBeatSubstate, Class<MusicBeatSubstate>>;
}
typedef OptionTypeDef = {
var type:Class<OptionType>;
var args:Array<Dynamic>;
}
@@ -2,7 +2,7 @@ package funkin.options.categories;
class AppearanceOptions extends OptionsScreen {
public override function new() {
super();
super("Appearance", "Change Appearance options such as Flashing menus...");
add(new Checkbox(
"Antialiasing",
"If unchecked, will disable antialiasing on every sprite. Can boost performances at the cost of sharper, more pixely sprites",
@@ -4,7 +4,7 @@ import funkin.windows.WindowsAPI;
class DebugOptions extends OptionsScreen {
public override function new() {
super();
super("Debug Options", "Use this menu to change debug options.");
#if windows
add(new TextOption(
"Show Console",
@@ -2,7 +2,7 @@ package funkin.options.categories;
class GameplayOptions extends OptionsScreen {
public override function new() {
super();
super("Gameplay", 'Change Gameplay options such as Downscroll, Scroll Speed, Naughtyness...');
add(new Checkbox(
"Downscroll",
"If checked, notes will go from up to down instead of down to up, like if they were falling",
@@ -3,7 +3,7 @@ package funkin.options.categories;
class MiscOptions extends OptionsScreen {
public override function new() {
super();
super("Miscellaneous", "Use this menu to reset save data or engine settings.");
#if UPDATE_CHECKING
add(new Checkbox(
"Enable Beta Updates",
+10 -3
View File
@@ -8,6 +8,8 @@ class Checkbox extends TextOption {
public var checkbox:FlxSprite;
public var checked:Bool;
public var parent:Dynamic;
private function get_selected() {
}
@@ -20,9 +22,14 @@ class Checkbox extends TextOption {
];
private var baseCheckboxOffset:FlxPoint = FlxPoint.get();
public function new(text:String, desc:String, optionName:String) {
public function new(text:String, desc:String, optionName:String, ?parent:Dynamic) {
super(text, desc, null);
if (parent == null)
parent = Options;
this.parent = parent;
checkbox = new FlxSprite(10, -40);
checkbox.frames = Paths.getFrames('menus/options/checkboxThingie');
checkbox.animation.addByPrefix("checked", "Check Box Selected Static", 24);
@@ -36,7 +43,7 @@ class Checkbox extends TextOption {
baseCheckboxOffset.set(checkbox.offset.x, checkbox.offset.y);
this.optionName = optionName;
checked = Reflect.field(Options, optionName);
checked = Reflect.field(parent, optionName);
}
public override function update(elapsed:Float) {
@@ -52,7 +59,7 @@ class Checkbox extends TextOption {
}
public override function onSelect() {
Reflect.setField(Options, optionName, checked = !checked);
Reflect.setField(parent, optionName, checked = !checked);
checkbox.animation.play("checking", true, !checked);
}