custom options????
This commit is contained in:
@@ -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
@@ -1 +1 @@
|
||||
2474
|
||||
2481
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user