Skip to content

Commit

Permalink
Added new settings items
Browse files Browse the repository at this point in the history
  • Loading branch information
FlooferLand committed Jul 1, 2024
1 parent 27bf88c commit 488fc68
Show file tree
Hide file tree
Showing 5 changed files with 366 additions and 50 deletions.
10 changes: 10 additions & 0 deletions source/funkin/ui/options/MenuItemEnums.hx
Original file line number Diff line number Diff line change
@@ -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";
}
*/
137 changes: 87 additions & 50 deletions source/funkin/ui/options/PreferencesMenu.hx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import funkin.ui.AtlasText.AtlasFont;
import funkin.ui.options.OptionsState.Page;
import funkin.graphics.FunkinCamera;
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
{
Expand Down Expand Up @@ -69,75 +74,107 @@ class PreferencesMenu extends Page
}, Preferences.autoPause);
}

function createPrefItemCheckbox(prefName:String, prefDesc:String, onChange:Bool->Void, defaultValue:Bool):Void
{
var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue);

items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() {
var value = !checkbox.currentValue;
onChange(value);
checkbox.currentValue = value;
});

preferenceItems.add(checkbox);
}

override function update(elapsed:Float)
override function update(elapsed:Float):Void
{
super.update(elapsed);

// Indent the selected item.
// TODO: Only do this on menu change?
items.forEach(function(daItem:TextMenuItem) {
if (items.selectedItem == daItem) daItem.x = 150;
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
daItem.x = 120;
{
thyOffset += 120;
}

daItem.x = thyOffset;
});
}
}

class CheckboxPreferenceItem extends FlxSprite
{
public var currentValue(default, set):Bool;
// - Preference item creation methods -
// Should be moved into a separate PreferenceItems class but you can't access PreferencesMenu.items and PreferencesMenu.preferenceItems from outside.

public function new(x:Float, y:Float, defaultValue:Bool = false)
/**
* 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
{
super(x, y);

frames = Paths.getSparrowAtlas('checkboxThingie');
animation.addByPrefix('static', 'Check Box unselected', 24, false);
animation.addByPrefix('checked', 'Check Box selecting animation', 24, false);
var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue);

setGraphicSize(Std.int(width * 0.7));
updateHitbox();
items.createItem(0, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() {
var value = !checkbox.currentValue;
onChange(value);
checkbox.currentValue = value;
});

this.currentValue = defaultValue;
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);
}

switch (animation.curAnim.name)
{
case 'static':
offset.set();
case 'checked':
offset.set(17, 70);
}
/**
* Creates a pref item that works with number percentages
* @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)
* @param min Minimum value (default = 0)
* @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) {
onChange(Std.int(value));
};
var formatter = function(value:Float) {
return '${value}%';
};
var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, 10, 0, newCallback, formatter);
items.addItem(prefName, item);
preferenceItems.add(item.lefthandText);
}

function set_currentValue(value:Bool):Bool
/**
* Creates a pref item that works with enums
* @param values Maps enum values to display strings _(ex: `NoteHitSoundType.PingPong => "Ping pong"`)_
* @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 createPrefItemEnum(prefName:String, prefDesc:String, values:Map<String, String>, onChange:String->Void, defaultValue:String):Void
{
if (value)
{
animation.play('checked', true);
}
else
{
animation.play('static');
}

return currentValue = value;
var item = new EnumPreferenceItem(0, (120 * items.length) + 30, prefName, values, defaultValue, onChange);
items.addItem(prefName, item);
preferenceItems.add(item.lefthandText);
}
}
49 changes: 49 additions & 0 deletions source/funkin/ui/options/items/CheckboxPreferenceItem.hx
Original file line number Diff line number Diff line change
@@ -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 changes: 84 additions & 0 deletions source/funkin/ui/options/items/EnumPreferenceItem.hx
Original file line number Diff line number Diff line change
@@ -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}';
}
}
Loading

0 comments on commit 488fc68

Please sign in to comment.