forked from FunkinCrew/Funkin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPreferencesMenu.hx
More file actions
279 lines (248 loc) · 11.4 KB
/
PreferencesMenu.hx
File metadata and controls
279 lines (248 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
package funkin.ui.options;
import flixel.FlxCamera;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.text.FlxText;
import flixel.util.FlxColor;
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
import funkin.ui.AtlasText.AtlasFont;
import funkin.ui.Page;
import funkin.graphics.FunkinCamera;
import funkin.graphics.FunkinSprite;
import funkin.ui.TextMenuList.TextMenuItem;
import funkin.ui.options.items.CheckboxPreferenceItem;
import funkin.ui.options.items.NumberPreferenceItem;
import funkin.ui.options.items.EnumPreferenceItem;
import lime.ui.WindowVSyncMode;
class PreferencesMenu extends Page<OptionsState.OptionsMenuPageName>
{
var items:TextMenuList;
var preferenceItems:FlxTypedSpriteGroup<FlxSprite>;
var preferenceDesc:Array<String> = [];
var itemDesc:FlxText;
var itemDescBox:FunkinSprite;
var menuCamera:FlxCamera;
var hudCamera:FlxCamera;
var camFollow:FlxObject;
public function new()
{
super();
menuCamera = new FunkinCamera('prefMenu');
FlxG.cameras.add(menuCamera, false);
menuCamera.bgColor = 0x0;
hudCamera = new FlxCamera();
FlxG.cameras.add(hudCamera, false);
hudCamera.bgColor = 0x0;
camera = menuCamera;
add(items = new TextMenuList());
add(preferenceItems = new FlxTypedSpriteGroup<FlxSprite>());
add(itemDescBox = new FunkinSprite());
itemDescBox.cameras = [hudCamera];
add(itemDesc = new FlxText(0, 0, 1180, null, 32));
itemDesc.cameras = [hudCamera];
createPrefItems();
createPrefDescription();
camFollow = new FlxObject(FlxG.width / 2, 0, 140, 70);
if (items != null) camFollow.y = items.selectedItem.y;
menuCamera.follow(camFollow, null, 0.085);
var margin = 160;
menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2);
menuCamera.minScrollY = 0;
items.onChange.add(function(selected) {
camFollow.y = selected.y;
itemDesc.text = preferenceDesc[items.selectedIndex];
});
}
/**
* Create the description for preferences.
*/
function createPrefDescription():Void
{
itemDescBox.makeSolidColor(1, 1, FlxColor.BLACK);
itemDescBox.alpha = 0.6;
itemDesc.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
itemDesc.borderSize = 3;
// Update the text.
itemDesc.text = preferenceDesc[items.selectedIndex];
itemDesc.screenCenter();
itemDesc.y += 270;
// Create the box around the text.
itemDescBox.setPosition(itemDesc.x - 10, itemDesc.y - 10);
itemDescBox.setGraphicSize(Std.int(itemDesc.width + 20), Std.int(itemDesc.height + 25));
itemDescBox.updateHitbox();
}
/**
* Create the menu items for each of the preferences.
*/
function createPrefItems():Void
{
createPrefItemCheckbox('Naughtyness', 'If enabled, raunchy content (such as swearing, etc.) will be displayed.', function(value:Bool):Void {
Preferences.naughtyness = value;
}, Preferences.naughtyness);
createPrefItemCheckbox('Downscroll', 'If enabled, this will make the notes move downwards.', function(value:Bool):Void {
Preferences.downscroll = value;
}, Preferences.downscroll);
createPrefItemPercentage('Strumline Background', 'Give the strumline a semi-transparent background', function(value:Int):Void {
Preferences.strumlineBackgroundOpacity = value;
}, Preferences.strumlineBackgroundOpacity);
createPrefItemCheckbox('Flashing Lights', 'If disabled, it will dampen flashing effects. Useful for people with photosensitive epilepsy.',
function(value:Bool):Void {
Preferences.flashingLights = value;
}, Preferences.flashingLights);
createPrefItemCheckbox('Camera Zooms', 'If disabled, camera stops bouncing to the song.', function(value:Bool):Void {
Preferences.zoomCamera = value;
}, Preferences.zoomCamera);
createPrefItemCheckbox('Debug Display', 'If enabled, FPS and other debug stats will be displayed.', function(value:Bool):Void {
Preferences.debugDisplay = value;
}, Preferences.debugDisplay);
createPrefItemCheckbox('Pause on Unfocus', 'If enabled, game automatically pauses when it loses focus.', function(value:Bool):Void {
Preferences.autoPause = value;
}, Preferences.autoPause);
createPrefItemCheckbox('Launch in Fullscreen', 'Automatically launch the game in fullscreen on startup', function(value:Bool):Void {
Preferences.autoFullscreen = value;
}, Preferences.autoFullscreen);
// disabled on macos due to "error: Late swap tearing currently unsupported"
#if !mac
createPrefItemEnum('VSync', 'If enabled, game will attempt to match framerate with your monitor.', [
"Off" => WindowVSyncMode.OFF,
"On" => WindowVSyncMode.ON,
"Adaptive" => WindowVSyncMode.ADAPTIVE,
], function(key:String, value:WindowVSyncMode):Void {
trace("Setting vsync mode to " + key);
Preferences.vsyncMode = value;
}, switch (Preferences.vsyncMode)
{
case WindowVSyncMode.OFF: "Off";
case WindowVSyncMode.ON: "On";
case WindowVSyncMode.ADAPTIVE: "Adaptive";
});
#end
#if web
createPrefItemCheckbox('Unlocked Framerate', 'If enabled, the framerate will be unlocked.', function(value:Bool):Void {
Preferences.unlockedFramerate = value;
}, Preferences.unlockedFramerate);
#else
createPrefItemNumber('FPS', 'The maximum framerate that the game targets.', function(value:Float) {
Preferences.framerate = Std.int(value);
}, null, Preferences.framerate, 30, 500, 5, 0);
#end
createPrefItemCheckbox('Hide Mouse', 'If enabled, the mouse will be hidden when taking a screenshot.', function(value:Bool):Void {
Preferences.shouldHideMouse = value;
}, Preferences.shouldHideMouse);
createPrefItemCheckbox('Fancy Preview', 'If enabled, a preview will be shown after taking a screenshot.', function(value:Bool):Void {
Preferences.fancyPreview = value;
}, Preferences.fancyPreview);
createPrefItemCheckbox('Preview on save', 'If enabled, the preview will be shown only after a screenshot is saved.', function(value:Bool):Void {
Preferences.previewOnSave = value;
}, Preferences.previewOnSave);
// TODO: having oValue is weird, probably change this later? was done to accomodate VSync changes.
createPrefItemEnum('Save Format', 'Save screenshots to this format.', ['PNG' => 'PNG', 'JPEG' => 'JPEG'], function(value:String, oValue:String):Void {
Preferences.saveFormat = value;
}, Preferences.saveFormat);
createPrefItemNumber('JPEG Quality', 'The quality of JPEG screenshots.', function(value:Float) {
Preferences.jpegQuality = Std.int(value);
}, null, Preferences.jpegQuality, 0, 100, 5, 0);
}
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;
switch (Type.typeof(daItem))
{
case TClass(CheckboxPreferenceItem):
thyTextWidth = 0;
thyOffset = 0;
case TClass(EnumPreferenceItem):
thyTextWidth = cast(daItem, EnumPreferenceItem<Dynamic>).lefthandText.getWidth();
thyOffset = 0 + thyTextWidth - 75;
case TClass(NumberPreferenceItem):
thyTextWidth = cast(daItem, NumberPreferenceItem).lefthandText.getWidth();
thyOffset = 0 + thyTextWidth - 75;
default:
// Huh?
}
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);
preferenceDesc.push(prefDesc);
}
/**
* 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);
preferenceDesc.push(prefDesc);
}
/**
* 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);
preferenceDesc.push(prefDesc);
}
/**
* 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<T>(prefName:String, prefDesc:String, values:Map<String, T>, onChange:String->T->Void, defaultKey:String):Void
{
var item = new EnumPreferenceItem<T>(0, (120 * items.length) + 30, prefName, values, defaultKey, onChange);
items.addItem(prefName, item);
preferenceItems.add(item.lefthandText);
preferenceDesc.push(prefDesc);
}
}