mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2024-11-15 11:22:55 +00:00
Added new settings items
This commit is contained in:
parent
8a4f19d603
commit
fbc78adb65
10
source/funkin/ui/options/MenuItemEnums.hx
Normal file
10
source/funkin/ui/options/MenuItemEnums.hx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package funkin.ui.options;
|
||||||
|
|
||||||
|
// Add enums for use with `EnumPreferenceItem` here!
|
||||||
|
/* Example:
|
||||||
|
class MyOptionEnum
|
||||||
|
{
|
||||||
|
public static inline var YuhUh = "true"; // "true" is the value's ID
|
||||||
|
public static inline var NuhUh = "false";
|
||||||
|
}
|
||||||
|
*/
|
|
@ -8,6 +8,11 @@ import funkin.ui.AtlasText.AtlasFont;
|
||||||
import funkin.ui.options.OptionsState.Page;
|
import funkin.ui.options.OptionsState.Page;
|
||||||
import funkin.graphics.FunkinCamera;
|
import funkin.graphics.FunkinCamera;
|
||||||
import funkin.ui.TextMenuList.TextMenuItem;
|
import funkin.ui.TextMenuList.TextMenuItem;
|
||||||
|
import funkin.audio.FunkinSound;
|
||||||
|
import funkin.ui.options.MenuItemEnums;
|
||||||
|
import funkin.ui.options.items.CheckboxPreferenceItem;
|
||||||
|
import funkin.ui.options.items.NumberPreferenceItem;
|
||||||
|
import funkin.ui.options.items.EnumPreferenceItem;
|
||||||
|
|
||||||
class PreferencesMenu extends Page
|
class PreferencesMenu extends Page
|
||||||
{
|
{
|
||||||
|
@ -69,11 +74,51 @@ class PreferencesMenu extends Page
|
||||||
}, Preferences.autoPause);
|
}, Preferences.autoPause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override function update(elapsed:Float):Void
|
||||||
|
{
|
||||||
|
super.update(elapsed);
|
||||||
|
|
||||||
|
// Indent the selected item.
|
||||||
|
items.forEach(function(daItem:TextMenuItem) {
|
||||||
|
var thyOffset:Int = 0;
|
||||||
|
|
||||||
|
// Initializing thy text width (if thou text present)
|
||||||
|
var thyTextWidth:Int = 0;
|
||||||
|
if (Std.isOfType(daItem, EnumPreferenceItem)) thyTextWidth = cast(daItem, EnumPreferenceItem).lefthandText.getWidth();
|
||||||
|
else if (Std.isOfType(daItem, NumberPreferenceItem)) thyTextWidth = cast(daItem, NumberPreferenceItem).lefthandText.getWidth();
|
||||||
|
|
||||||
|
if (thyTextWidth != 0)
|
||||||
|
{
|
||||||
|
// Magic number because of the weird offset thats being added by default
|
||||||
|
thyOffset += thyTextWidth - 75;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items.selectedItem == daItem)
|
||||||
|
{
|
||||||
|
thyOffset += 150;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thyOffset += 120;
|
||||||
|
}
|
||||||
|
|
||||||
|
daItem.x = thyOffset;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Preference item creation methods -
|
||||||
|
// Should be moved into a separate PreferenceItems class but you can't access PreferencesMenu.items and PreferencesMenu.preferenceItems from outside.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a pref item that works with booleans
|
||||||
|
* @param onChange Gets called every time the player changes the value; use this to apply the value
|
||||||
|
* @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable)
|
||||||
|
*/
|
||||||
function createPrefItemCheckbox(prefName:String, prefDesc:String, onChange:Bool->Void, defaultValue:Bool):Void
|
function createPrefItemCheckbox(prefName:String, prefDesc:String, onChange:Bool->Void, defaultValue:Bool):Void
|
||||||
{
|
{
|
||||||
var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue);
|
var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue);
|
||||||
|
|
||||||
items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() {
|
items.createItem(0, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() {
|
||||||
var value = !checkbox.currentValue;
|
var value = !checkbox.currentValue;
|
||||||
onChange(value);
|
onChange(value);
|
||||||
checkbox.currentValue = value;
|
checkbox.currentValue = value;
|
||||||
|
@ -82,62 +127,54 @@ class PreferencesMenu extends Page
|
||||||
preferenceItems.add(checkbox);
|
preferenceItems.add(checkbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function update(elapsed:Float)
|
/**
|
||||||
|
* Creates a pref item that works with general numbers
|
||||||
|
* @param onChange Gets called every time the player changes the value; use this to apply the value
|
||||||
|
* @param valueFormatter Will get called every time the game needs to display the float value; use this to change how the displayed value looks
|
||||||
|
* @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable)
|
||||||
|
* @param min Minimum value (example: 0)
|
||||||
|
* @param max Maximum value (example: 10)
|
||||||
|
* @param step The value to increment/decrement by (default = 0.1)
|
||||||
|
* @param precision Rounds decimals up to a `precision` amount of digits (ex: 4 -> 0.1234, 2 -> 0.12)
|
||||||
|
*/
|
||||||
|
function createPrefItemNumber(prefName:String, prefDesc:String, onChange:Float->Void, ?valueFormatter:Float->String, defaultValue:Int, min:Int, max:Int,
|
||||||
|
step:Float = 0.1, precision:Int):Void
|
||||||
{
|
{
|
||||||
super.update(elapsed);
|
var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange, valueFormatter);
|
||||||
|
items.addItem(prefName, item);
|
||||||
|
preferenceItems.add(item.lefthandText);
|
||||||
|
}
|
||||||
|
|
||||||
// Indent the selected item.
|
/**
|
||||||
// TODO: Only do this on menu change?
|
* Creates a pref item that works with number percentages
|
||||||
items.forEach(function(daItem:TextMenuItem) {
|
* @param onChange Gets called every time the player changes the value; use this to apply the value
|
||||||
if (items.selectedItem == daItem) daItem.x = 150;
|
* @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable)
|
||||||
else
|
* @param min Minimum value (default = 0)
|
||||||
daItem.x = 120;
|
* @param max Maximum value (default = 100)
|
||||||
});
|
*/
|
||||||
}
|
function createPrefItemPercentage(prefName:String, prefDesc:String, onChange:Int->Void, defaultValue:Int, min:Int = 0, max:Int = 100):Void
|
||||||
}
|
{
|
||||||
|
var newCallback = function(value:Float) {
|
||||||
class CheckboxPreferenceItem extends FlxSprite
|
onChange(Std.int(value));
|
||||||
{
|
};
|
||||||
public var currentValue(default, set):Bool;
|
var formatter = function(value:Float) {
|
||||||
|
return '${value}%';
|
||||||
public function new(x:Float, y:Float, defaultValue:Bool = false)
|
};
|
||||||
{
|
var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, 10, 0, newCallback, formatter);
|
||||||
super(x, y);
|
items.addItem(prefName, item);
|
||||||
|
preferenceItems.add(item.lefthandText);
|
||||||
frames = Paths.getSparrowAtlas('checkboxThingie');
|
}
|
||||||
animation.addByPrefix('static', 'Check Box unselected', 24, false);
|
|
||||||
animation.addByPrefix('checked', 'Check Box selecting animation', 24, false);
|
/**
|
||||||
|
* Creates a pref item that works with enums
|
||||||
setGraphicSize(Std.int(width * 0.7));
|
* @param values Maps enum values to display strings _(ex: `NoteHitSoundType.PingPong => "Ping pong"`)_
|
||||||
updateHitbox();
|
* @param onChange Gets called every time the player changes the value; use this to apply the value
|
||||||
|
* @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable)
|
||||||
this.currentValue = defaultValue;
|
*/
|
||||||
}
|
function createPrefItemEnum(prefName:String, prefDesc:String, values:Map<String, String>, onChange:String->Void, defaultValue:String):Void
|
||||||
|
{
|
||||||
override function update(elapsed:Float)
|
var item = new EnumPreferenceItem(0, (120 * items.length) + 30, prefName, values, defaultValue, onChange);
|
||||||
{
|
items.addItem(prefName, item);
|
||||||
super.update(elapsed);
|
preferenceItems.add(item.lefthandText);
|
||||||
|
|
||||||
switch (animation.curAnim.name)
|
|
||||||
{
|
|
||||||
case 'static':
|
|
||||||
offset.set();
|
|
||||||
case 'checked':
|
|
||||||
offset.set(17, 70);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_currentValue(value:Bool):Bool
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
animation.play('checked', true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
animation.play('static');
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentValue = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
49
source/funkin/ui/options/items/CheckboxPreferenceItem.hx
Normal file
49
source/funkin/ui/options/items/CheckboxPreferenceItem.hx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package funkin.ui.options.items;
|
||||||
|
|
||||||
|
import flixel.FlxSprite.FlxSprite;
|
||||||
|
|
||||||
|
class CheckboxPreferenceItem extends FlxSprite
|
||||||
|
{
|
||||||
|
public var currentValue(default, set):Bool;
|
||||||
|
|
||||||
|
public function new(x:Float, y:Float, defaultValue:Bool = false)
|
||||||
|
{
|
||||||
|
super(x, y);
|
||||||
|
|
||||||
|
frames = Paths.getSparrowAtlas('checkboxThingie');
|
||||||
|
animation.addByPrefix('static', 'Check Box unselected', 24, false);
|
||||||
|
animation.addByPrefix('checked', 'Check Box selecting animation', 24, false);
|
||||||
|
|
||||||
|
setGraphicSize(Std.int(width * 0.7));
|
||||||
|
updateHitbox();
|
||||||
|
|
||||||
|
this.currentValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
override function update(elapsed:Float)
|
||||||
|
{
|
||||||
|
super.update(elapsed);
|
||||||
|
|
||||||
|
switch (animation.curAnim.name)
|
||||||
|
{
|
||||||
|
case 'static':
|
||||||
|
offset.set();
|
||||||
|
case 'checked':
|
||||||
|
offset.set(17, 70);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_currentValue(value:Bool):Bool
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
animation.play('checked', true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
animation.play('static');
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentValue = value;
|
||||||
|
}
|
||||||
|
}
|
84
source/funkin/ui/options/items/EnumPreferenceItem.hx
Normal file
84
source/funkin/ui/options/items/EnumPreferenceItem.hx
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
package funkin.ui.options.items;
|
||||||
|
|
||||||
|
import funkin.ui.TextMenuList;
|
||||||
|
import funkin.ui.AtlasText;
|
||||||
|
import funkin.input.Controls;
|
||||||
|
import funkin.ui.options.MenuItemEnums;
|
||||||
|
import haxe.EnumTools;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preference item that allows the player to pick a value from an enum (list of values)
|
||||||
|
*/
|
||||||
|
class EnumPreferenceItem extends TextMenuItem
|
||||||
|
{
|
||||||
|
function controls():Controls
|
||||||
|
{
|
||||||
|
return PlayerSettings.player1.controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public var lefthandText:AtlasText;
|
||||||
|
|
||||||
|
public var currentValue:String;
|
||||||
|
public var onChangeCallback:Null<String->Void>;
|
||||||
|
public var map:Map<String, String>;
|
||||||
|
public var keys:Array<String> = [];
|
||||||
|
|
||||||
|
var index = 0;
|
||||||
|
|
||||||
|
public function new(x:Float, y:Float, name:String, map:Map<String, String>, defaultValue:String, ?callback:String->Void)
|
||||||
|
{
|
||||||
|
super(x, y, name, function() {
|
||||||
|
callback(this.currentValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
updateHitbox();
|
||||||
|
|
||||||
|
this.map = map;
|
||||||
|
this.currentValue = defaultValue;
|
||||||
|
this.onChangeCallback = callback;
|
||||||
|
|
||||||
|
var i:Int = 0;
|
||||||
|
for (key in map.keys())
|
||||||
|
{
|
||||||
|
this.keys.push(key);
|
||||||
|
if (this.currentValue == key) index = i;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lefthandText = new AtlasText(15, y, formatted(defaultValue), AtlasFont.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function update(elapsed:Float):Void
|
||||||
|
{
|
||||||
|
super.update(elapsed);
|
||||||
|
|
||||||
|
// var fancyTextFancyColor:Color;
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
var shouldDecrease:Bool = controls().UI_LEFT_P;
|
||||||
|
var shouldIncrease:Bool = controls().UI_RIGHT_P;
|
||||||
|
|
||||||
|
if (shouldDecrease) index -= 1;
|
||||||
|
if (shouldIncrease) index += 1;
|
||||||
|
|
||||||
|
if (index > keys.length - 1) index = 0;
|
||||||
|
if (index < 0) index = keys.length - 1;
|
||||||
|
|
||||||
|
currentValue = keys[index];
|
||||||
|
if (onChangeCallback != null && (shouldIncrease || shouldDecrease))
|
||||||
|
{
|
||||||
|
onChangeCallback(currentValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lefthandText.text = formatted(currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatted(value:String):String
|
||||||
|
{
|
||||||
|
// FIXME: Can't add arrows around the text because the font doesn't support < >
|
||||||
|
// var leftArrow:String = selected ? '<' : '';
|
||||||
|
// var rightArrow:String = selected ? '>' : '';
|
||||||
|
return '${map.get(value) ?? value}';
|
||||||
|
}
|
||||||
|
}
|
136
source/funkin/ui/options/items/NumberPreferenceItem.hx
Normal file
136
source/funkin/ui/options/items/NumberPreferenceItem.hx
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
package funkin.ui.options.items;
|
||||||
|
|
||||||
|
import funkin.ui.TextMenuList;
|
||||||
|
import funkin.ui.AtlasText;
|
||||||
|
import funkin.input.Controls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preference item that allows the player to pick a value between min and max
|
||||||
|
*/
|
||||||
|
class NumberPreferenceItem extends TextMenuItem
|
||||||
|
{
|
||||||
|
function controls():Controls
|
||||||
|
{
|
||||||
|
return PlayerSettings.player1.controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
public var lefthandText:AtlasText;
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
static final HOLD_DELAY:Float = 0.3; // seconds
|
||||||
|
static final CHANGE_RATE:Float = 0.08; // seconds
|
||||||
|
|
||||||
|
// Constructor-initialized variables
|
||||||
|
public var currentValue:Float;
|
||||||
|
public var min:Float;
|
||||||
|
public var max:Float;
|
||||||
|
public var step:Float;
|
||||||
|
public var precision:Int;
|
||||||
|
public var onChangeCallback:Null<Float->Void>;
|
||||||
|
public var valueFormatter:Null<Float->String>;
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
var holdDelayTimer:Float = HOLD_DELAY; // seconds
|
||||||
|
var changeRateTimer:Float = 0.0; // seconds
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param min Minimum value (example: 0)
|
||||||
|
* @param max Maximum value (example: 100)
|
||||||
|
* @param step The value to increment/decrement by (example: 10)
|
||||||
|
* @param callback Will get called every time the user changes the setting; use this to apply/save the setting.
|
||||||
|
* @param valueFormatter Will get called every time the game needs to display the float value; use this to change how the displayed string looks
|
||||||
|
*/
|
||||||
|
public function new(x:Float, y:Float, name:String, defaultValue:Float, min:Float, max:Float, step:Float, precision:Int, ?callback:Float->Void,
|
||||||
|
?valueFormatter:Float->String):Void
|
||||||
|
{
|
||||||
|
super(x, y, name, function() {
|
||||||
|
callback(this.currentValue);
|
||||||
|
});
|
||||||
|
lefthandText = new AtlasText(15, y, formatted(defaultValue), AtlasFont.DEFAULT);
|
||||||
|
|
||||||
|
updateHitbox();
|
||||||
|
|
||||||
|
this.currentValue = defaultValue;
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.step = step;
|
||||||
|
this.precision = precision;
|
||||||
|
this.onChangeCallback = callback;
|
||||||
|
this.valueFormatter = valueFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
override function update(elapsed:Float):Void
|
||||||
|
{
|
||||||
|
super.update(elapsed);
|
||||||
|
|
||||||
|
// var fancyTextFancyColor:Color;
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
holdDelayTimer -= elapsed;
|
||||||
|
if (holdDelayTimer <= 0.0)
|
||||||
|
{
|
||||||
|
changeRateTimer -= elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
var jpLeft:Bool = controls().UI_LEFT_P;
|
||||||
|
var jpRight:Bool = controls().UI_RIGHT_P;
|
||||||
|
|
||||||
|
if (jpLeft || jpRight)
|
||||||
|
{
|
||||||
|
holdDelayTimer = HOLD_DELAY;
|
||||||
|
changeRateTimer = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var shouldDecrease:Bool = jpLeft;
|
||||||
|
var shouldIncrease:Bool = jpRight;
|
||||||
|
|
||||||
|
if (controls().UI_LEFT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0)
|
||||||
|
{
|
||||||
|
shouldDecrease = true;
|
||||||
|
changeRateTimer = CHANGE_RATE;
|
||||||
|
}
|
||||||
|
else if (controls().UI_RIGHT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0)
|
||||||
|
{
|
||||||
|
shouldIncrease = true;
|
||||||
|
changeRateTimer = CHANGE_RATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually increasing/decreasing the value
|
||||||
|
if (shouldDecrease)
|
||||||
|
{
|
||||||
|
var isBelowMin:Bool = currentValue - step < min;
|
||||||
|
currentValue = (currentValue - step).clamp(min, max);
|
||||||
|
if (onChangeCallback != null && !isBelowMin) onChangeCallback(currentValue);
|
||||||
|
}
|
||||||
|
else if (shouldIncrease)
|
||||||
|
{
|
||||||
|
var isAboveMax:Bool = currentValue + step > max;
|
||||||
|
currentValue = (currentValue + step).clamp(min, max);
|
||||||
|
if (onChangeCallback != null && !isAboveMax) onChangeCallback(currentValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lefthandText.text = formatted(currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Turns the float into a string */
|
||||||
|
function formatted(value:Float):String
|
||||||
|
{
|
||||||
|
var float:Float = toFixed(value);
|
||||||
|
if (valueFormatter != null)
|
||||||
|
{
|
||||||
|
return valueFormatter(float);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return '${float}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toFixed(value:Float):Float
|
||||||
|
{
|
||||||
|
var multiplier:Float = Math.pow(10, precision);
|
||||||
|
return Math.floor(value * multiplier) / multiplier;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue