Files
FNF-i486-Engine/source/options/BaseOptionsMenu.hx

532 lines
13 KiB
Haxe

package options;
import Controls;
import flixel.addons.ui.FlxUIInputText; // These are both for the search bars
import flixel.graphics.FlxGraphic;
import flixel.input.keyboard.FlxKey;
import flixel.ui.FlxButton;
class BaseOptionsMenu extends MusicBeatSubstate
{
private var curOption:Option = null;
private var curSelected:Int = 0;
private var optionsArray:Array<Option>;
private var grpOptions:FlxTypedGroup<Alphabet>;
private var checkboxGroup:FlxTypedGroup<CheckboxThingie>;
private var grpTexts:FlxTypedGroup<AttachedText>;
private var boyfriend:Character = null;
private var descBox:FlxSprite;
private var descText:FlxText;
var optionSearchText:FlxUIInputText;
var searchText:FlxText;
public var title:String;
public var rpcTitle:String;
public function new()
{
super();
if (title == null)
title = 'Options';
if (rpcTitle == null)
rpcTitle = 'Options Menu';
#if desktop
DiscordClient.changePresence(rpcTitle, null);
#end
var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
bg.color = 0xFFea71fd;
bg.screenCenter();
bg.antialiasing = ClientPrefs.globalAntialiasing;
add(bg);
// avoids lagspikes while scrolling through menus!
grpOptions = new FlxTypedGroup<Alphabet>();
add(grpOptions);
grpTexts = new FlxTypedGroup<AttachedText>();
add(grpTexts);
checkboxGroup = new FlxTypedGroup<CheckboxThingie>();
add(checkboxGroup);
descBox = new FlxSprite().makeGraphic(1, 1, FlxColor.BLACK);
descBox.alpha = 0.6;
add(descBox);
var titleText:Alphabet = new Alphabet(75, 40, title, true);
titleText.scaleX = 0.6;
titleText.scaleY = 0.6;
titleText.alpha = 0.4;
add(titleText);
descText = new FlxText(50, 600, 1180, "", 32);
descText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
descText.scrollFactor.set();
descText.borderSize = 2.4;
add(descText);
for (i in 0...optionsArray.length)
{
var optionText:Alphabet = new Alphabet(290, 260, optionsArray[i].name, false);
optionText.isMenuItem = true;
/*optionText.forceX = 300;
optionText.yMult = 90; */
optionText.targetY = i;
grpOptions.add(optionText);
if (optionsArray[i].type == 'bool')
{
var checkbox:CheckboxThingie = new CheckboxThingie(optionText.x - 105, optionText.y, optionsArray[i].getValue() == true);
checkbox.sprTracker = optionText;
checkbox.ID = i;
checkboxGroup.add(checkbox);
}
else if (optionsArray[i].type != 'link')
{
optionText.x -= 80;
optionText.startPosition.x -= 80;
// optionText.xAdd -= 80;
var valueText:AttachedText = new AttachedText('' + optionsArray[i].getValue(), optionText.width + 80);
valueText.sprTracker = optionText;
valueText.copyAlpha = true;
valueText.ID = i;
grpTexts.add(valueText);
optionsArray[i].setChild(valueText);
}
// optionText.snapToPosition(); //Don't ignore me when i ask for not making a fucking pull request to uncomment this line ok
if (optionsArray[i].showBoyfriend && boyfriend == null)
{
reloadBoyfriend();
}
updateTextFrom(optionsArray[i]);
}
changeSelection();
reloadCheckboxes();
originalOptionsArray = optionsArray.copy();
optionSearchText = new FlxUIInputText(0, 0, 500, '', 16);
optionSearchText.x = FlxG.width - optionSearchText.width;
add(optionSearchText);
var buttonTop:FlxButton = new FlxButton(0, optionSearchText.y + optionSearchText.height + 5, "", function()
{
optionsSearch(optionSearchText.text);
});
buttonTop.setGraphicSize(Std.int(optionSearchText.width), 50);
buttonTop.updateHitbox();
buttonTop.label.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.BLACK, RIGHT);
buttonTop.x = FlxG.width - buttonTop.width;
add(buttonTop);
searchText = new FlxText(975, buttonTop.y + 20, 100, "Search", 24);
searchText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.BLACK);
add(searchText);
FlxG.mouse.visible = true;
}
public function addOption(option:Option)
{
if (optionsArray == null || optionsArray.length < 1)
optionsArray = [];
optionsArray.push(option);
}
var originalOptionsArray:Array<Option> = [];
var optionsFound:Array<Option> = [];
function optionsSearch(?query:String = '')
{
optionsFound = [];
var foundOptions:Int = 0;
final txt:FlxText = new FlxText(0, 0, 0, 'No options found matching your query', 16);
txt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
txt.scrollFactor.set();
txt.screenCenter(XY);
for (i in 0...originalOptionsArray.length)
{
if (query != null && query.length > 0)
{
var optionName = originalOptionsArray[i].name.toLowerCase();
var q = query.toLowerCase();
if (optionName.indexOf(q) != -1)
{
optionsFound.push(originalOptionsArray[i]);
foundOptions++;
}
}
}
if (foundOptions > 0 || query.length <= 0)
{
if (txt != null)
remove(txt); // don't do destroy/kill on this btw
regenerateOptions(query);
}
else if (foundOptions <= 0)
{
add(txt);
new FlxTimer().start(3, function(timer)
{
if (txt != null)
remove(txt);
});
return;
}
}
function regenerateOptions(?query:String = '')
{
if (query.length > 0)
optionsArray = optionsFound;
else if (optionsArray != originalOptionsArray)
optionsArray = originalOptionsArray.copy();
regenList();
}
function regenList()
{
grpOptions.forEach(option ->
{
grpOptions.remove(option, true);
option.destroy();
});
grpTexts.forEach(text ->
{
grpTexts.remove(text, true);
text.destroy();
});
checkboxGroup.forEach(check ->
{
checkboxGroup.remove(check, true);
check.destroy();
});
// we clear the remaining ones
grpOptions.clear();
grpTexts.clear();
checkboxGroup.clear();
for (i in 0...optionsArray.length)
{
var optionText:Alphabet = new Alphabet(290, 260, optionsArray[i].name, false);
optionText.isMenuItem = true;
/*optionText.forceX = 300;
optionText.yMult = 90; */
optionText.targetY = i;
grpOptions.add(optionText);
if (optionsArray[i].type == 'bool')
{
var checkbox:CheckboxThingie = new CheckboxThingie(optionText.x - 105, optionText.y, optionsArray[i].getValue() == true);
checkbox.sprTracker = optionText;
checkbox.ID = i;
checkboxGroup.add(checkbox);
}
else if (optionsArray[i].type != 'link')
{
optionText.x -= 80;
optionText.startPosition.x -= 80;
// optionText.xAdd -= 80;
var valueText:AttachedText = new AttachedText('' + optionsArray[i].getValue(), optionText.width + 80);
valueText.sprTracker = optionText;
valueText.copyAlpha = true;
valueText.ID = i;
grpTexts.add(valueText);
optionsArray[i].setChild(valueText);
}
// optionText.snapToPosition(); //Don't ignore me when i ask for not making a fucking pull request to uncomment this line ok
if (optionsArray[i].showBoyfriend && boyfriend == null)
{
reloadBoyfriend();
}
updateTextFrom(optionsArray[i]);
}
changeSelection();
reloadCheckboxes();
}
var nextAccept:Int = 5;
var holdTime:Float = 0;
var holdValue:Float = 0;
override function update(elapsed:Float)
{
if (!optionSearchText.hasFocus)
{
if (controls.UI_UP_P)
{
changeSelection(-1);
}
if (controls.UI_DOWN_P)
{
changeSelection(1);
}
if (controls.BACK)
{
close();
FlxG.sound.play(Paths.sound('cancelMenu'));
}
if (nextAccept <= 0)
{
var usesCheckbox = true;
if (curOption.type != 'bool')
{
usesCheckbox = false;
}
if (usesCheckbox)
{
if (controls.ACCEPT)
{
FlxG.sound.play(Paths.sound((curOption.type == 'link' ? 'confirmMenu' : 'scrollMenu')));
if (curOption.type == 'bool')
curOption.setValue((curOption.getValue() == true) ? false : true);
curOption.change();
reloadCheckboxes();
}
}
else
{
if (controls.UI_LEFT || controls.UI_RIGHT)
{
var pressed = (controls.UI_LEFT_P || controls.UI_RIGHT_P);
if (holdTime > 0.5 || pressed)
{
if (pressed)
{
var add:Dynamic = null;
if (curOption.type != 'string')
{
add = controls.UI_LEFT ? -curOption.changeValue : curOption.changeValue;
}
switch (curOption.type)
{
case 'int' | 'float' | 'percent':
holdValue = curOption.getValue() + add;
if (holdValue < curOption.minValue)
holdValue = curOption.minValue;
else if (holdValue > curOption.maxValue)
holdValue = curOption.maxValue;
switch (curOption.type)
{
case 'int':
holdValue = Math.round(holdValue);
curOption.setValue(holdValue);
case 'float' | 'percent':
holdValue = FlxMath.roundDecimal(holdValue, curOption.decimals);
curOption.setValue(holdValue);
}
case 'string':
var num:Int = curOption.curOption; // lol
if (controls.UI_LEFT_P)
--num;
else
num++;
if (num < 0)
{
num = curOption.options.length - 1;
}
else if (num >= curOption.options.length)
{
num = 0;
}
curOption.curOption = num;
curOption.setValue(curOption.options[num]); // lol
// trace(curOption.options[num]);
}
updateTextFrom(curOption);
curOption.change();
FlxG.sound.play(Paths.sound('scrollMenu'));
}
else if (curOption.type != 'string')
{
holdValue += curOption.scrollSpeed * elapsed * (controls.UI_LEFT ? -1 : 1);
if (holdValue < curOption.minValue)
holdValue = curOption.minValue;
else if (holdValue > curOption.maxValue)
holdValue = curOption.maxValue;
switch (curOption.type)
{
case 'int':
curOption.setValue(Math.round(holdValue));
case 'float' | 'percent':
curOption.setValue(FlxMath.roundDecimal(holdValue, curOption.decimals));
}
updateTextFrom(curOption);
curOption.change();
}
}
if (curOption.type != 'string')
{
holdTime += elapsed;
}
}
else if (controls.UI_LEFT_R || controls.UI_RIGHT_R)
{
clearHold();
}
}
if (controls.RESET)
{
if (!FlxG.keys.pressed.SHIFT)
{
var leOption:Option = optionsArray[curSelected];
leOption.setValue(leOption.defaultValue);
if (leOption.type != 'bool')
{
if (leOption.type == 'string')
{
leOption.curOption = leOption.options.indexOf(leOption.getValue());
}
updateTextFrom(leOption);
}
leOption.change();
}
else
for (i in 0...optionsArray.length)
{
var leOption:Option = optionsArray[i];
leOption.setValue(leOption.defaultValue);
if (leOption.type != 'bool')
{
if (leOption.type == 'string')
{
leOption.curOption = leOption.options.indexOf(leOption.getValue());
}
updateTextFrom(leOption);
}
leOption.change();
}
FlxG.sound.play(Paths.sound('cancelMenu'));
reloadCheckboxes();
}
}
}
if (boyfriend != null && boyfriend.animation.curAnim.finished)
{
boyfriend.dance();
}
if (nextAccept > 0)
{
nextAccept -= 1;
}
super.update(elapsed);
}
function updateTextFrom(option:Option)
{
var text:String = option.displayFormat;
var val:Dynamic = option.getValue();
if (option.type == 'percent')
val *= 100;
var def:Dynamic = option.defaultValue;
option.text = text.replace('%v', val).replace('%d', def);
}
function clearHold()
{
if (holdTime > 0.5)
{
FlxG.sound.play(Paths.sound('scrollMenu'));
}
holdTime = 0;
}
function changeSelection(change:Int = 0)
{
curSelected += change;
if (curSelected < 0)
curSelected = optionsArray.length - 1;
if (curSelected >= optionsArray.length)
curSelected = 0;
descText.text = optionsArray[curSelected].description;
descText.screenCenter(Y);
descText.y += 270;
var bullShit:Int = 0;
for (item in grpOptions.members)
{
item.targetY = bullShit - curSelected;
bullShit++;
item.alpha = 0.6;
if (item.targetY == 0)
{
item.alpha = 1;
}
}
for (text in grpTexts)
{
text.alpha = 0.6;
if (text.ID == curSelected)
{
text.alpha = 1;
}
}
descBox.setPosition(descText.x - 10, descText.y - 10);
descBox.setGraphicSize(Std.int(descText.width + 20), Std.int(descText.height + 25));
descBox.updateHitbox();
if (boyfriend != null)
{
boyfriend.visible = optionsArray[curSelected].showBoyfriend;
}
curOption = optionsArray[curSelected]; // shorter lol
FlxG.sound.play(Paths.sound('scrollMenu'));
}
public function reloadBoyfriend()
{
var wasVisible:Bool = false;
if (boyfriend != null)
{
wasVisible = boyfriend.visible;
boyfriend.kill();
remove(boyfriend);
boyfriend.destroy();
}
boyfriend = new Character(840, 170, 'bf', true);
boyfriend.setGraphicSize(Std.int(boyfriend.width * 0.75));
boyfriend.updateHitbox();
boyfriend.dance();
insert(1, boyfriend);
boyfriend.visible = wasVisible;
}
function reloadCheckboxes()
{
for (checkbox in checkboxGroup)
{
checkbox.daValue = (optionsArray[checkbox.ID].getValue() == true);
}
}
}