package funkin.ui.options; import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; 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 { var items:TextMenuList; var preferenceItems:FlxTypedSpriteGroup; var menuCamera:FlxCamera; var camFollow:FlxObject; public function new() { super(); menuCamera = new FunkinCamera('prefMenu'); FlxG.cameras.add(menuCamera, false); menuCamera.bgColor = 0x0; camera = menuCamera; add(items = new TextMenuList()); add(preferenceItems = new FlxTypedSpriteGroup()); createPrefItems(); camFollow = new FlxObject(FlxG.width / 2, 0, 140, 70); if (items != null) camFollow.y = items.selectedItem.y; menuCamera.follow(camFollow, null, 0.06); var margin = 160; menuCamera.deadzone.set(0, margin, menuCamera.width, 40); menuCamera.minScrollY = 0; items.onChange.add(function(selected) { camFollow.y = selected.y; }); } /** * Create the menu items for each of the preferences. */ function createPrefItems():Void { createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void { Preferences.naughtyness = value; }, Preferences.naughtyness); createPrefItemCheckbox('Downscroll', 'Enable to make notes move downwards', function(value:Bool):Void { Preferences.downscroll = value; }, Preferences.downscroll); createPrefItemCheckbox('Flashing Lights', 'Disable to dampen flashing effects', function(value:Bool):Void { Preferences.flashingLights = value; }, Preferences.flashingLights); createPrefItemCheckbox('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', function(value:Bool):Void { Preferences.zoomCamera = value; }, Preferences.zoomCamera); createPrefItemCheckbox('Debug Display', 'Enable to show FPS and other debug stats', function(value:Bool):Void { Preferences.debugDisplay = value; }, Preferences.debugDisplay); createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void { Preferences.autoPause = value; }, Preferences.autoPause); #if web createPrefItemCheckbox('Unlocked Framerate', 'Enable to unlock the framerate', function(value:Bool):Void { Preferences.unlockedFramerate = value; }, Preferences.unlockedFramerate); #end } 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 { var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue); items.createItem(0, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { var value = !checkbox.currentValue; onChange(value); checkbox.currentValue = value; }); preferenceItems.add(checkbox); } /** * 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 { 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); } /** * 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); } /** * 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, onChange:String->Void, defaultValue:String):Void { var item = new EnumPreferenceItem(0, (120 * items.length) + 30, prefName, values, defaultValue, onChange); items.addItem(prefName, item); preferenceItems.add(item.lefthandText); } }