mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
- Updated the handling of the option slider entries to utilize temp vars and properly complied the audio channel options to the new setup - Fixed issue where behavior of slider was erratic because of improperly defined tick count - Added logic to check if audio sliders were changed for the 'check unchanged settings' logic - Made the keybind remap inputCtrl ignore axis events - Made the MessageBoxDlg input commands properly check for key makes, to prevent messages boxes from catching key breaks and blowing past follow-up messageboxes accidentally - Fixed forward/backward iteration of options entries, especially on dpad, and added handling for gamepad stick to do the same - Added logic so option sliders can also be manipulated by the forward/backward to make it standard for all - Fixed erroneous marking of "restart required" message as true if any settings change, and not just settings expressly flagged as requiring a restart
1058 lines
34 KiB
Plaintext
1058 lines
34 KiB
Plaintext
$optionsEntryPad = 10;
|
|
|
|
$OptionsMenuCategories[0] = "Video";
|
|
$OptionsMenuCategories[1] = "Audio";
|
|
$OptionsMenuCategories[2] = "KBM";
|
|
$OptionsMenuCategories[3] = "Controller";
|
|
|
|
function OptionsMenu::onAdd(%this)
|
|
{
|
|
if(!isObject(%this.optionsCategories))
|
|
{
|
|
%this.optionsCategories = new ArrayObject();
|
|
}
|
|
|
|
%this.currentCategory = "";
|
|
|
|
callOnModules("populateOptionsMenuCategories", "Game");
|
|
}
|
|
|
|
function OptionsMenu::onWake(%this)
|
|
{
|
|
$optionsChangeRequiresRestart = false;
|
|
|
|
%this.populateVideoSettings();
|
|
|
|
%this.populateAudioSettings();
|
|
|
|
%this.populateKBMControls();
|
|
|
|
%this.populateGamepadControls();
|
|
//establish the cached prefs values here
|
|
|
|
%this.openOptionsCategory("Video");
|
|
}
|
|
|
|
if(!isObject( OptionsMenuActionMap ) )
|
|
{
|
|
new ActionMap(OptionsMenuActionMap){};
|
|
|
|
OptionsMenuActionMap.bind( keyboard, Escape, tryCloseOptionsMenu);
|
|
OptionsMenuActionMap.bind( gamepad, btn_b, tryCloseOptionsMenu);
|
|
|
|
OptionsMenuActionMap.bind( keyboard, w, OptionMenuNavigatePrev );
|
|
OptionsMenuActionMap.bind( keyboard, s, OptionMenuNavigateNext );
|
|
OptionsMenuActionMap.bind( gamepad, yaxis, "D", "-0.23 0.23", OptionMenuStickNavigate );
|
|
OptionsMenuActionMap.bind( gamepad, upov, OptionMenuNavigatePrev );
|
|
OptionsMenuActionMap.bind( gamepad, dpov, OptionMenuNavigateNext );
|
|
|
|
OptionsMenuActionMap.bind( keyboard, a, OptionMenuPrevSetting );
|
|
OptionsMenuActionMap.bind( keyboard, d, OptionMenuNextSetting );
|
|
OptionsMenuActionMap.bind( gamepad, xaxis, "D", "-0.23 0.23", OptionMenuStickChangeSetting );
|
|
OptionsMenuActionMap.bind( gamepad, lpov, OptionMenuPrevSetting );
|
|
OptionsMenuActionMap.bind( gamepad, rpov, OptionMenuNextSetting );
|
|
|
|
OptionsMenuActionMap.bind( keyboard, q, OptionsMenuPrevCategory );
|
|
OptionsMenuActionMap.bind( gamepad, btn_l, OptionsMenuPrevCategory );
|
|
|
|
OptionsMenuActionMap.bind( keyboard, e, OptionsMenuNextCategory );
|
|
OptionsMenuActionMap.bind( gamepad, btn_r, OptionsMenuNextCategory );
|
|
|
|
OptionsMenuActionMap.bind( keyboard, R, OptionsMenuReset );
|
|
OptionsMenuActionMap.bind( gamepad, btn_x, OptionsMenuReset );
|
|
|
|
OptionsMenuActionMap.bind( keyboard, Space, OptionsMenuActivateOption );
|
|
OptionsMenuActionMap.bind( gamepad, btn_a, OptionsMenuActivateOption );
|
|
|
|
OptionsMenuActionMap.bind( keyboard, Enter, tryApplyOptions);
|
|
OptionsMenuActionMap.bind( gamepad, btn_start, tryApplyOptions);
|
|
}
|
|
|
|
//==============================================================================
|
|
// This function updates all the elements in the actual lists to ensure they're
|
|
// sized, stylized and formatted correctly, as well as up to date values
|
|
function OptionsMenuList::syncGui(%this)
|
|
{
|
|
%this.callOnChildren("setHighlighted", false);
|
|
|
|
%btn = %this.getObject(%this.listPosition);
|
|
if(%btn.class $= "OptionsListEntry" ||
|
|
%btn.class $= "OptionsListSliderEntry" ||
|
|
%btn.class $= "OptionsKeybindEntry")
|
|
%btn-->button.setHighlighted(true);
|
|
|
|
//iterate over the items and ensure that they are formatted well based on the settings selected
|
|
foreach(%option in %this)
|
|
{
|
|
%container = %option-->valuesContainer;
|
|
|
|
if(%option.class $= "OptionsListEntry")
|
|
{
|
|
%hasLevels = %option.optionsObject.getCount() <= 1;
|
|
|
|
%optionObject = %option.optionsObject;
|
|
|
|
//If it's out of range of the options, it's probably a custom value
|
|
if(%option.currentOptionIndex < %optionObject.getCount() && %option.currentOptionIndex >= 0)
|
|
{
|
|
%currentOptionLevel = %optionObject.getObject(%option.currentOptionIndex);
|
|
%currentOptionLevelTxt = %currentOptionLevel.displayName;
|
|
}
|
|
else
|
|
{
|
|
%currentOptionLevelTxt = "Custom";
|
|
}
|
|
|
|
%optionValTextWidth = %option-->optionValue.profile.getStringWidth(%currentOptionLevelTxt);
|
|
|
|
%option-->optionValue.resize(%container.extent.x - %container-->prevValButton.extent.x - %optionValTextWidth - 20, 0,
|
|
%optionValTextWidth + 20, %container.extent.y);
|
|
|
|
%option-->optionValue.text = %currentOptionLevelTxt;
|
|
|
|
%container-->prevValButton.position.x = %option-->optionValue.position.x - 20;
|
|
%container-->nextValButton.position.x = %container.extent.x - %container-->prevValButton.extent.x;
|
|
|
|
//if there's no alternatives, disable the left/right buttons
|
|
%container-->prevValButton.setHidden(%hasLevels);
|
|
%container-->nextValButton.setHidden(%hasLevels);
|
|
}
|
|
else if(%option.class $= "OptionsListSliderEntry")
|
|
{
|
|
}
|
|
else if(%option.class $= "OptionsKeybindEntry")
|
|
{
|
|
%bindImgAsset = getButtonBitmap(%option.device, getField(%option.keymap, 1));
|
|
|
|
if(%bindImgAsset $= "UI:Keyboard_Black_Blank_image")
|
|
%bindImgAsset = "";
|
|
|
|
%container-->bindButton.setBitmap(%bindImgAsset);
|
|
}
|
|
}
|
|
}
|
|
|
|
function OptionsMenuList::checkForUnappliedChanges(%this)
|
|
{
|
|
%unappliedChanges = false;
|
|
|
|
foreach(%option in %this)
|
|
{
|
|
if(%option.class $= "OptionsListEntry")
|
|
{
|
|
if(%option.currentOptionIndex >= 0 && %option.currentOptionIndex < %option.optionsObject.getCount())
|
|
{
|
|
%targetOptionLevel = %option.optionsObject.getObject(%option.currentOptionIndex);
|
|
|
|
if(!%targetOptionLevel.isCurrent())
|
|
%unappliedChanges = true;
|
|
|
|
if(%unappliedChanges && %option.optionsObject.requiresRestart)
|
|
$optionsChangeRequiresRestart = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return %unappliedChanges;
|
|
}
|
|
|
|
function OptionsMenuList::applyChanges(%this)
|
|
{
|
|
foreach(%option in %this)
|
|
{
|
|
if(%option.class $= "OptionsListEntry")
|
|
{
|
|
//If it's custom or nonsensical index, there's some kind of external factor going on, so we're
|
|
//just going to skip applying it because we don't know what we'd be applying
|
|
if(%option.currentOptionIndex >= 0 && %option.currentOptionIndex < %option.optionsObject.getCount())
|
|
{
|
|
%targetOptionLevel = %option.optionsObject.getObject(%option.currentOptionIndex);
|
|
|
|
if(!%targetOptionLevel.isCurrent())
|
|
%targetOptionLevel.apply();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function OptionsMenu::openOptionsCategory(%this, %categoryName)
|
|
{
|
|
VideoSettingsList.setVisible(%categoryName $= "Video");
|
|
AudioSettingsList.setVisible(%categoryName $= "Audio");
|
|
KBMControlsList.setVisible(%categoryName $= "KBM");
|
|
GamepadControlsList.setVisible(%categoryName $= "Controller");
|
|
|
|
if(%categoryName $= "Video")
|
|
{
|
|
$MenuList = VideoSettingsList;
|
|
//Find our first non-group entry
|
|
while($MenuList.getObject($MenuList.listPosition).class !$= OptionsListEntry && $MenuList.listPosition < $MenuList.getCount())
|
|
{
|
|
$MenuList.listPosition += 1;
|
|
}
|
|
|
|
%this.currentCatgeoryIdx = 0;
|
|
}
|
|
else if(%categoryName $= "Audio")
|
|
{
|
|
$MenuList = AudioSettingsList;
|
|
|
|
%this.currentCatgeoryIdx = 1;
|
|
}
|
|
else if(%categoryName $= "KBM")
|
|
{
|
|
$MenuList = KBMControlsList;
|
|
|
|
%this.currentCatgeoryIdx = 2;
|
|
}
|
|
else if(%categoryName $= "Controller")
|
|
{
|
|
$MenuList = GamepadControlsList;
|
|
|
|
%this.currentCatgeoryIdx = 3;
|
|
}
|
|
|
|
$MenuList.syncGui();
|
|
%this.syncGui();
|
|
}
|
|
|
|
//==============================================================================
|
|
// This function updates the non-list items of the menu to be up to date and stylistically
|
|
// complaint. This ensures keybind hint buttons are presented correctly based on the current input
|
|
// device
|
|
function OptionsMenu::syncGui(%this)
|
|
{
|
|
OptionsMenuCategoryList.callOnChildren("setHighlighted", false);
|
|
|
|
%btn = OptionsMenuCategoryList.getObject(%this.currentCatgeoryIdx);
|
|
%btn.setHighlighted(true);
|
|
|
|
%buttonPosX = %btn.position.x + OptionsMenuCategoryList.position.x;
|
|
|
|
OptionsMenuPrevNavIcon.position.x = %buttonPosX - 5;
|
|
OptionsMenuNextNavIcon.position.x = %buttonPosX + %btn.extent.x - 35;
|
|
|
|
//Update the button imagery to comply to the last input device we'd used
|
|
%device = Canvas.getLastInputDevice();
|
|
if(%device $= "mouse")
|
|
%device = "keyboard";
|
|
|
|
OptionsMenuBackBtn.setBitmap(BaseUIActionMap.getCommandButtonBitmap(%device, "BaseUIBackOut"));
|
|
OptionsMenuResetBtn.setBitmap(OptionsMenuActionMap.getCommandButtonBitmap(%device, "OptionsMenuReset"));
|
|
|
|
OptionsMenuPrevNavIcon.setBitmap(OptionsMenuActionMap.getCommandButtonBitmap(%device, "OptionsMenuPrevCategory"));
|
|
OptionsMenuNextNavIcon.setBitmap(OptionsMenuActionMap.getCommandButtonBitmap(%device, "OptionsMenuNextCategory"));
|
|
|
|
OptionsMenuApplyBtn.setBitmap(OptionsMenuActionMap.getCommandButtonBitmap(%device, "tryApplyOptions"));
|
|
|
|
OptionsMenuRemapBtn.visible = KBMControlsList.visible || GamepadControlsList.visible;
|
|
OptionsMenuRemapBtn.setBitmap(OptionsMenuActionMap.getCommandButtonBitmap(%device, "OptionsMenuActivateOption"));
|
|
}
|
|
|
|
//==============================================================================
|
|
// Menu navigation functions
|
|
// Primarily used by keybinds
|
|
function OptionsMenuPrevCategory(%val)
|
|
{
|
|
if(%val)
|
|
{
|
|
%currentIdx = OptionsMenu.currentMenuIdx;
|
|
OptionsMenu.currentMenuIdx -= 1;
|
|
|
|
OptionsMenu.currentMenuIdx = mClamp(OptionsMenu.currentMenuIdx, 0, 3);
|
|
|
|
if(%currentIdx == OptionsMenu.currentMenuIdx)
|
|
return;
|
|
|
|
%newCategory = $OptionsMenuCategories[OptionsMenu.currentMenuIdx];
|
|
OptionsMenu.openOptionsCategory(%newCategory);
|
|
}
|
|
}
|
|
|
|
function OptionsMenuNextCategory(%val)
|
|
{
|
|
if(%val)
|
|
{
|
|
%currentIdx = OptionsMenu.currentMenuIdx;
|
|
OptionsMenu.currentMenuIdx += 1;
|
|
|
|
OptionsMenu.currentMenuIdx = mClamp(OptionsMenu.currentMenuIdx, 0, 3);
|
|
|
|
if(%currentIdx == OptionsMenu.currentMenuIdx)
|
|
return;
|
|
|
|
%newCategory = $OptionsMenuCategories[OptionsMenu.currentMenuIdx];
|
|
OptionsMenu.openOptionsCategory(%newCategory);
|
|
}
|
|
}
|
|
|
|
function OptionMenuNavigatePrev(%val)
|
|
{
|
|
if(%val)
|
|
{
|
|
$MenuList.listPosition -= 1;
|
|
while( $MenuList.listPosition >= 0 && ($MenuList.getObject($MenuList.listPosition).class !$= "OptionsListEntry" &&
|
|
$MenuList.getObject($MenuList.listPosition).class !$= "OptionsListSliderEntry" &&
|
|
$MenuList.getObject($MenuList.listPosition).class !$= "OptionsKeybindEntry"))
|
|
{
|
|
$MenuList.listPosition -= 1;
|
|
}
|
|
|
|
if($MenuList.listPosition < 0)
|
|
$MenuList.listPosition = 0;
|
|
|
|
$MenuList.syncGUI();
|
|
|
|
$BaseUI::scrollSchedule = schedule($BaseUI::scrollSpeedTimeMs, 0, "OptionMenuNavigatePrev", 1);
|
|
}
|
|
else
|
|
{
|
|
cancel($BaseUI::scrollSchedule);
|
|
}
|
|
}
|
|
|
|
function OptionMenuNavigateNext(%val)
|
|
{
|
|
if(%val)
|
|
{
|
|
$MenuList.listPosition += 1;
|
|
while($MenuList.listPosition < $MenuList.getCount() && ($MenuList.getObject($MenuList.listPosition).class !$= "OptionsListEntry" &&
|
|
$MenuList.getObject($MenuList.listPosition).class !$= "OptionsListSliderEntry" &&
|
|
$MenuList.getObject($MenuList.listPosition).class !$= "OptionsKeybindEntry"))
|
|
{
|
|
$MenuList.listPosition += 1;
|
|
}
|
|
|
|
if($MenuList.listPosition >= $MenuList.getCount())
|
|
$MenuList.listPosition = $MenuList.getCount()-1;
|
|
|
|
$MenuList.syncGUI();
|
|
|
|
$BaseUI::scrollSchedule = schedule($BaseUI::scrollSpeedTimeMs, 0, "OptionMenuNavigateNext", 1);
|
|
}
|
|
else
|
|
{
|
|
cancel($BaseUI::scrollSchedule);
|
|
}
|
|
}
|
|
|
|
function OptionMenuStickNavigate(%val)
|
|
{
|
|
if(%val == 1)
|
|
OptionMenuNavigateNext(1);
|
|
else if(%val == -1)
|
|
OptionMenuNavigatePrev(1);
|
|
else
|
|
cancel($BaseUI::scrollSchedule);
|
|
}
|
|
|
|
function OptionMenuPrevSetting(%val)
|
|
{
|
|
if(!%val)
|
|
return;
|
|
|
|
%option = $MenuList.getObject($MenuList.listPosition);
|
|
|
|
if(!isObject(%option))
|
|
return;
|
|
|
|
if(%option.class $= "OptionsListEntry")
|
|
{
|
|
%optionObject = %option.optionsObject;
|
|
%currentOptionLevel = %optionObject.getObject(%option.currentOptionIndex);
|
|
|
|
%option.currentOptionIndex = mClamp(%option.currentOptionIndex-1, 0, %optionObject.getCount()-1);
|
|
|
|
%newOptionLevel = %optionObject.getObject(%option.currentOptionIndex);
|
|
|
|
//echo("Changed option: " @ %optionObject.optionName @ " from level: " @ %currentOptionLevel.displayName @ " to level: " @ %newOptionLevel.displayName);
|
|
}
|
|
else if(%option.class $= "OptionsListSliderEntry")
|
|
{
|
|
%sliderCtrl = %option-->valuesContainer-->slider;
|
|
%minValue = %sliderCtrl.range.x;
|
|
%maxValue = %sliderCtrl.range.y;
|
|
%ticks = %sliderCtrl.ticks;
|
|
|
|
%tickIncrementVal = (%maxValue - %minValue) / %ticks;
|
|
|
|
%sliderCtrl.value -= %tickIncrementVal;
|
|
}
|
|
|
|
$MenuList.syncGUI();
|
|
}
|
|
|
|
function OptionMenuNextSetting(%val)
|
|
{
|
|
if(!%val)
|
|
return;
|
|
|
|
%option = $MenuList.getObject($MenuList.listPosition);
|
|
|
|
if(!isObject(%option) )
|
|
return;
|
|
|
|
if(%option.class $= "OptionsListEntry")
|
|
{
|
|
%optionObject = %option.optionsObject;
|
|
%currentOptionLevel = %optionObject.getObject(%option.currentOptionIndex);
|
|
|
|
%option.currentOptionIndex = mClamp(%option.currentOptionIndex+1, 0, %optionObject.getCount()-1);
|
|
|
|
%newOptionLevel = %optionObject.getObject(%option.currentOptionIndex);
|
|
|
|
//echo("Changed option: " @ %optionObject.optionName @ " from level: " @ %currentOptionLevel.displayName @ " to level: " @ %newOptionLevel.displayName);
|
|
}
|
|
else if(%option.class $= "OptionsListSliderEntry")
|
|
{
|
|
%sliderCtrl = %option-->valuesContainer-->slider;
|
|
%minValue = %sliderCtrl.range.x;
|
|
%maxValue = %sliderCtrl.range.y;
|
|
%ticks = %sliderCtrl.ticks;
|
|
|
|
%tickIncrementVal = (%maxValue - %minValue) / %ticks;
|
|
|
|
%sliderCtrl.value += %tickIncrementVal;
|
|
}
|
|
|
|
$MenuList.syncGUI();
|
|
}
|
|
|
|
function OptionMenuStickChangeSetting(%val)
|
|
{
|
|
if(%val == 1)
|
|
OptionMenuNextSetting(1);
|
|
else if(%val == -1)
|
|
OptionMenuPrevSetting(1);
|
|
}
|
|
|
|
function OptionsMenuActivateOption(%val)
|
|
{
|
|
if(!%val)
|
|
return;
|
|
|
|
%option = $MenuList.getObject($MenuList.listPosition);
|
|
|
|
if(!isObject(%option))
|
|
return;
|
|
|
|
if(%option.class $= "OptionsKeybindEntry")
|
|
{
|
|
%option-->button.execAltCommand();
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// This function utilizes the VideoSettingsGroup SimGroup to populate options.
|
|
// The object is defined in core/rendering/scripts/graphicsOptions.tscript
|
|
// A majority of the options are statically defined, but some are dynamically populated
|
|
// on refresh, like the display device or available resolution options.
|
|
// Once populated, we loop over the simgroup structure to populate our option entry
|
|
// rows in the options menu itself.
|
|
function OptionsMenu::populateVideoSettings(%this)
|
|
{
|
|
VideoSettingsList.clear();
|
|
|
|
VideoSettingsGroup::populateDisplaySettings();
|
|
|
|
for(%i=0; %i < VideoSettingsGroup.getCount(); %i++)
|
|
{
|
|
%setting = VideoSettingsGroup.getObject(%i);
|
|
|
|
if(%setting.class $= "SubOptionsGroup")
|
|
{
|
|
%entry = addOptionGroup(%setting.displayName);
|
|
|
|
if(isObject(%entry))
|
|
VideoSettingsList.add(%entry);
|
|
|
|
for(%s=0; %s < %setting.getCount(); %s++)
|
|
{
|
|
%option = %setting.getObject(%s);
|
|
|
|
%optionsEntry = addOptionEntry(%option);
|
|
|
|
if(isObject(%optionsEntry))
|
|
VideoSettingsList.add(%optionsEntry);
|
|
}
|
|
}
|
|
else if(%setting.class $= "OptionsSettings")
|
|
{
|
|
%optionsEntry = addOptionEntry(%setting);
|
|
|
|
if(isObject(%optionsEntry))
|
|
VideoSettingsList.add(%optionsEntry);
|
|
}
|
|
}
|
|
|
|
//Ensure our newly templated options listings are sized right
|
|
for(%i=0; %i < VideoSettingsList.getCount(); %i++)
|
|
{
|
|
%entry = VideoSettingsList.getObject(%i);
|
|
%entry.resize(0, 0, VideoSettingsList.extent.x - 15, %entry.extent.y); //-10 for the scroll wheel pad
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// This function utilizes the AudioSettingsGroup SimGroup to populate options.
|
|
// The object is defined in core/sfx/scripts/audioOptions.tscript
|
|
// Similar to the video options, it can be a mix of static and dynamically populated
|
|
// option entries, which we then iterate over and populate the entry rows for the menu
|
|
function OptionsMenu::populateAudioSettings(%this)
|
|
{
|
|
AudioSettingsList.clear();
|
|
AudioSettingsGroup.populateSettings();
|
|
|
|
//Process the lists
|
|
for(%i=0; %i < AudioSettingsGroup.getCount(); %i++)
|
|
{
|
|
%setting = AudioSettingsGroup.getObject(%i);
|
|
|
|
if(%setting.class $= "SubOptionsGroup")
|
|
{
|
|
%entry = addOptionGroup(%setting.displayName);
|
|
|
|
if(isObject(%entry))
|
|
AudioSettingsList.add(%entry);
|
|
|
|
for(%s=0; %s < %setting.getCount(); %s++)
|
|
{
|
|
%option = %setting.getObject(%s);
|
|
|
|
%optionsEntry = addOptionEntry(%option);
|
|
|
|
if(isObject(%optionsEntry))
|
|
AudioSettingsList.add(%optionsEntry);
|
|
}
|
|
}
|
|
else if(%setting.class $= "AudioOptionsSettings")
|
|
{
|
|
%optionsEntry = addOptionEntry(%setting);
|
|
|
|
if(isObject(%optionsEntry))
|
|
AudioSettingsList.add(%optionsEntry);
|
|
}
|
|
}
|
|
|
|
AudioSettingsList.add(addOptionGroup("Channel Volume"));
|
|
|
|
//Now we'll populate the sliders for the audio channels.
|
|
//The defaults of these are defined in core/sfx/scripts/audio.tscript
|
|
//These define the MasterVolume channel, as well as several other common defualt ones
|
|
//Because it's a variable list, this can be expanded by modules by just upping $AudioChannelCount
|
|
//and then defining the $AudioChannelName[x] with the displayed name and
|
|
//and the $AudioChannels[x] variable with the SFXSource object defined to it for the given channel
|
|
AudioSettingsList.add(addOptionSlider("Master Volume", "", "$pref::SFX::masterVolume", 0, 1, 10));
|
|
|
|
//We init to 1, because 0 is the reserved for the masterVolume in practice
|
|
for(%i=1; %i < $AudioChannelCount; %i++)
|
|
{
|
|
AudioSettingsList.add(addOptionSlider($AudioChannelsName[%i] @ " Volume", "", "$pref::SFX::channelVolume" @ %i, 0, 1, 10));
|
|
}
|
|
|
|
//Ensure our newly templated options listings are sized right
|
|
for(%i=0; %i < AudioSettingsList.getCount(); %i++)
|
|
{
|
|
%entry = AudioSettingsList.getObject(%i);
|
|
%entry.resize(0, 0, AudioSettingsList.extent.x - 15, %entry.extent.y); //-10 for the scroll wheel pad
|
|
}
|
|
}
|
|
|
|
function OptionsMenu::populateKBMControls(%this)
|
|
{
|
|
%this.populateKeybinds("keyboard", KBMControlsList);
|
|
|
|
%this.syncGui();
|
|
|
|
KBMControlsList.syncGui();
|
|
}
|
|
|
|
function OptionsMenu::populateGamepadControls(%this)
|
|
{
|
|
%this.populateKeybinds("gamepad", GamepadControlsList);
|
|
|
|
%this.syncGui();
|
|
|
|
GamepadControlsList.syncGui();
|
|
}
|
|
|
|
function OptionsMenu::populateKeybinds(%this, %device, %controlsList)
|
|
{
|
|
%controlsList.clear();
|
|
|
|
//build out our list of action maps
|
|
%actionMapCount = ActionMapGroup.getCount();
|
|
|
|
%actionMapList = "";
|
|
for(%i=0; %i < %actionMapCount; %i++)
|
|
{
|
|
%actionMap = ActionMapGroup.getObject(%i);
|
|
|
|
if(%actionMap == GlobalActionMap.getId())
|
|
continue;
|
|
|
|
%actionMapName = %actionMap.humanReadableName $= "" ? %actionMap.getName() : %actionMap.humanReadableName;
|
|
|
|
//see if we have any actual listed remappable keys for this movemap. if so, drop it from the listing
|
|
%hasRemaps = false;
|
|
for ( %r = 0; %r < $RemapCount; %r++ )
|
|
{
|
|
%testMapName = $RemapActionMap[%r].humanReadableName $= "" ? $RemapActionMap[%r].getName() : $RemapActionMap[%r].humanReadableName;
|
|
|
|
if(%actionMapName $= %testMapName)
|
|
{
|
|
//got a match to at least one, so we're ok to continue
|
|
%hasRemaps = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!%hasRemaps)
|
|
continue;
|
|
|
|
if(%actionMapList $= "")
|
|
%actionMapList = %actionMapName;
|
|
else
|
|
%actionMapList = %actionMapList TAB %actionMapName;
|
|
}
|
|
|
|
//If we didn't find any valid actionMaps, then just exit out
|
|
if(%actionMapList $= "")
|
|
return;
|
|
|
|
if($activeRemapControlSet $= "")
|
|
$activeRemapControlSet = getField(%actionMapList, 0);
|
|
|
|
for(%am = 0; %am < getFieldCount(%actionMapList); %am++)
|
|
{
|
|
%currentActionMap = getField(%actionMapList, %am);
|
|
|
|
//only add the group if we've got more than one group, otherwise it's obviously
|
|
//part of the single grouping
|
|
if(getFieldCount(%actionMapList) > 1)
|
|
{
|
|
%actionMapGroupEntry = addOptionGroup(%currentActionMap);
|
|
%controlsList.add(%actionMapGroupEntry);
|
|
}
|
|
|
|
for ( %i = 0; %i < $RemapCount; %i++ )
|
|
{
|
|
if(%device !$= "" && %device !$= $RemapDevice[%i])
|
|
continue;
|
|
|
|
%actionMapName = $RemapActionMap[%i].humanReadableName $= "" ? $RemapActionMap[%i].getName() : $RemapActionMap[%i].humanReadableName;
|
|
|
|
if(%currentActionMap !$= %actionMapName)
|
|
continue;
|
|
|
|
%keyMap = buildFullMapString( %i, $RemapActionMap[%i], %device );
|
|
|
|
%description = $RemapDescription[%i];
|
|
|
|
%remapEntry = addActionMapEntry(%actionMapName, %device, %keyMap, %i, %description);
|
|
%controlsList.add(%remapEntry);
|
|
}
|
|
}
|
|
|
|
//Ensure our newly templated options listings are sized right
|
|
for(%i=0; %i < %controlsList.getCount(); %i++)
|
|
{
|
|
%entry = %controlsList.getObject(%i);
|
|
%entry.resize(0, 0, %controlsList.extent.x - 15, %entry.extent.y); //-10 for the scroll wheel pad
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
function tryCloseOptionsMenu(%val)
|
|
{
|
|
if(!%val)
|
|
return;
|
|
|
|
$optionsChangeRequiresRestart = false;
|
|
|
|
%unappliedVideoChanges = VideoSettingsList.checkForUnappliedChanges();
|
|
%unappliedAudioChanges = AudioSettingsList.checkForUnappliedChanges();
|
|
|
|
//validate audio prefs
|
|
if($pref::SFX::masterVolume_tempVar !$= "" && $pref::SFX::masterVolume_tempVar != $pref::SFX::masterVolume)
|
|
%unappliedAudioChanges = true;
|
|
|
|
for(%i=1; %i < $AudioChannelCount; %i++)
|
|
{
|
|
%tempVolume = getVariable("$pref::SFX::channelVolume" @ %i @ "_tempVar");
|
|
if(%tempVolume !$= "" && $pref::SFX::channelVolume[ %i ] != %tempVolume)
|
|
%unappliedAudioChanges = true;
|
|
}
|
|
|
|
if(%unappliedVideoChanges || %unappliedAudioChanges)
|
|
{
|
|
MessageBoxOKCancel("Discard Changes?", "You have unapplied changes to your settings, do you wish to apply or discard them?",
|
|
"OptionsMenu.applyChangedOptions();", "Canvas.popDialog(OptionsMenu);",
|
|
"Apply", "Discard");
|
|
}
|
|
else
|
|
{
|
|
BaseUIBackOut(1);
|
|
}
|
|
}
|
|
|
|
function tryApplyOptions(%val)
|
|
{
|
|
if(!%val)
|
|
return;
|
|
|
|
$optionsChangeRequiresRestart = false;
|
|
|
|
%unappliedVideoChanges = VideoSettingsList.checkForUnappliedChanges();
|
|
%unappliedAudioChanges = AudioSettingsList.checkForUnappliedChanges();
|
|
|
|
if(%unappliedVideoChanges || %unappliedAudioChanges)
|
|
OptionsMenu.applyChangedOptions();
|
|
}
|
|
|
|
function OptionsMenu::applyChangedOptions(%this)
|
|
{
|
|
VideoSettingsList.applyChanges();
|
|
AudioSettingsList.applyChanges();
|
|
|
|
//Process the audio channel tempvars to get their values
|
|
//and then apply them to the actual pref variable, as well as the SFXChannelVolume
|
|
$pref::SFX::masterVolume = $pref::SFX::masterVolume_tempVar;
|
|
sfxSetMasterVolume( $pref::SFX::masterVolume );
|
|
|
|
//0 is always master anyways
|
|
for(%i=1; %i < $AudioChannelCount; %i++)
|
|
{
|
|
%volume = getVariable("$pref::SFX::channelVolume" @ %i @ "_tempVar");
|
|
sfxSetChannelVolume( %i, %volume );
|
|
$pref::SFX::channelVolume[ %i ] = %volume;
|
|
}
|
|
|
|
//Finally, write our prefs to file
|
|
%prefPath = getPrefpath();
|
|
export("$pref::*", %prefPath @ "/clientPrefs." @ $TorqueScriptFileExtension, false);
|
|
|
|
BaseUIBackOut(1);
|
|
|
|
if($optionsChangeRequiresRestart)
|
|
MessageBoxOK("Restart Required", "Some of your changes require the game to be restarted.");
|
|
}
|
|
|
|
function doKeyRemap( %optionEntry )
|
|
{
|
|
%name = getField(%optionEntry.keymap,0);
|
|
|
|
RemapDlg-->OptRemapText.text = "Re-bind \"" @ %name @ "\" to..." ;
|
|
OptRemapInputCtrl.index = %optionEntry.remapIndex;
|
|
|
|
$remapListDevice = %optionEntry.device;
|
|
|
|
Canvas.pushDialog( RemapDlg );
|
|
}
|
|
|
|
function OptionsMenu::resetSettings(%this)
|
|
{
|
|
MessageBoxOKCancel("", "This will set the graphical settings back to the auto-detected defaults. Do you wish to continue?", "AutodetectGraphics();", "");
|
|
}
|
|
|
|
//==============================================================================
|
|
// Option types
|
|
function addOptionGroup(%displayName)
|
|
{
|
|
%group = new GuiTextCtrl() {
|
|
text = %displayName;
|
|
position = "0 0";
|
|
extent = "500 45";
|
|
profile = "MenuHeaderText";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
};
|
|
|
|
return %group;
|
|
}
|
|
|
|
function optionsMenuButton::onHighlighted(%this, %highlighted)
|
|
{
|
|
%container = %this.getParent();
|
|
|
|
%container-->optionName.profile = %highlighted ? MenuSubHeaderTextHighlighted : MenuSubHeaderText;
|
|
%container-->optionDescription.profile = %highlighted ? GuiMLTextProfileHighlighted : GuiMLTextProfile;
|
|
|
|
%valuesContainer = %container-->valuesContainer;
|
|
%valuesContainer-->optionValue.profile = %highlighted ? GuiMenuTextProfileHL : GuiMenuTextProfile;
|
|
|
|
OptionsMenuSettingsScroll.scrollToObject(%container);
|
|
}
|
|
|
|
function addOptionEntry(%optionObj)
|
|
{
|
|
if(!isObject(%optionObj) || (%optionObj.class !$= "OptionsSettings" && %optionObj.class !$= "AudioOptionsSettings"))
|
|
{
|
|
error("addOptionsEntry() - attempting to create a new options entry, but was provided an invalid options object");
|
|
return 0;
|
|
}
|
|
|
|
%qualityLevel = getCurrentQualityLevel(%optionObj);
|
|
|
|
if(isObject(%qualityLevel))
|
|
{
|
|
%qualityLevelText = %qualityLevel.displayName;
|
|
%qualityLevelIndex = %optionObj.getObjectIndex(%qualityLevel);
|
|
}
|
|
else
|
|
{
|
|
%qualityLevelText = %qualityLevel;
|
|
%qualityLevelIndex = %optionObj.getCount();
|
|
}
|
|
|
|
%optionNameHeight = 20;
|
|
if(%optionObj.Description $= "")
|
|
%optionNameHeight = 40;
|
|
|
|
%entry = new GuiContainer() {
|
|
position = "0 0";
|
|
extent = "800 40";
|
|
profile = GuiMenuDefaultProfile;
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
horizSizing = "width";
|
|
vertSizing = "bottom";
|
|
class = "OptionsListEntry";
|
|
optionsObject = %optionObj;
|
|
currentOptionIndex = %qualityLevelIndex;
|
|
canSave = "0";
|
|
|
|
new GuiButtonCtrl() {
|
|
profile = GuiMenuButtonProfile;
|
|
position = "0 0";
|
|
extent = "800 40";
|
|
horizSizing = "width";
|
|
vertSizing = "height";
|
|
internalName = "button";
|
|
class = "optionsMenuButton";
|
|
};
|
|
|
|
new GuiTextCtrl() {
|
|
text = %optionObj.OptionName;
|
|
position = $optionsEntryPad SPC -1;
|
|
extent = 400 SPC %optionNameHeight;
|
|
profile = "MenuSubHeaderText";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
internalName = "optionName";
|
|
};
|
|
new GuiTextCtrl() {
|
|
text = %optionObj.Description;
|
|
position = $optionsEntryPad SPC 17;
|
|
extent = "400 18";
|
|
profile = "GuiMLTextProfile";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
internalName = "optionDescription";
|
|
};
|
|
|
|
new GuiContainer() {
|
|
position = "400 0";
|
|
extent = "400 40";
|
|
profile = GuiModelessDialogProfile;
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
horizSizing = "left";
|
|
vertSizing = "height";
|
|
internalName = "valuesContainer";
|
|
|
|
new GuiButtonCtrl() {
|
|
position = "310 0";
|
|
extent = "20 40";
|
|
text = "<";
|
|
profile = GuiMenuButtonProfile;
|
|
internalName = "prevValButton";
|
|
};
|
|
|
|
new GuiTextCtrl() {
|
|
text = %qualityLevelText;
|
|
position = "330 0";
|
|
extent = "50 40";
|
|
profile = "GuiMenuTextProfile";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
horizSizing = "right";
|
|
vertSizing = "center";
|
|
internalName = "optionValue";
|
|
};
|
|
|
|
new GuiButtonCtrl() {
|
|
position = "380 0";
|
|
extent = "20 40";
|
|
text = ">";
|
|
profile = GuiMenuButtonProfile;
|
|
internalName = "nextValButton";
|
|
};
|
|
};
|
|
};
|
|
|
|
return %entry;
|
|
}
|
|
|
|
function addOptionSlider(%optionName, %optionDesc, %prefName, %sliderMin, %sliderMax, %sliderTicks)
|
|
{
|
|
%currentVal = getVariable(%prefName);
|
|
|
|
%tempVarName = %prefName @ "_tempVar";
|
|
|
|
if(%currentVal $= "")
|
|
%currentVal = %sliderMin;
|
|
|
|
setVariable(%tempVarName, %currentVal);
|
|
|
|
%optionNameHeight = 20;
|
|
if(%optionDesc $= "")
|
|
%optionNameHeight = 40;
|
|
|
|
%entry = new GuiContainer() {
|
|
position = "0 0";
|
|
extent = "800 40";
|
|
profile = GuiMenuDefaultProfile;
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
horizSizing = "width";
|
|
vertSizing = "bottom";
|
|
class = "OptionsListSliderEntry";
|
|
canSave = "0";
|
|
|
|
new GuiButtonCtrl() {
|
|
profile = GuiMenuButtonProfile;
|
|
position = "0 0";
|
|
extent = "800 40";
|
|
horizSizing = "width";
|
|
vertSizing = "height";
|
|
internalName = "button";
|
|
class = "optionsMenuButton";
|
|
};
|
|
|
|
new GuiTextCtrl() {
|
|
text = %optionName;
|
|
position = $optionsEntryPad SPC -1;
|
|
extent = 400 SPC %optionNameHeight;
|
|
profile = "MenuSubHeaderText";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
internalName = "optionName";
|
|
};
|
|
|
|
new GuiTextCtrl() {
|
|
text = %optionDesc;
|
|
position = $optionsEntryPad SPC 17;
|
|
extent = "400 18";
|
|
profile = "GuiMLTextProfile";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
internalName = "optionDescription";
|
|
};
|
|
|
|
new GuiContainer() {
|
|
position = "400 0";
|
|
extent = "400 40";
|
|
profile = GuiModelessDialogProfile;
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
horizSizing = "left";
|
|
vertSizing = "height";
|
|
internalName = "valuesContainer";
|
|
|
|
new GuiSliderCtrl() {
|
|
range = %sliderMin SPC %sliderMax;
|
|
ticks = %sliderTicks;
|
|
snap = "1";
|
|
value = %currentVal;
|
|
variable = %tempVarName;
|
|
useFillBar = "1";
|
|
fillBarColor = $TextMediumEmphasisColor;
|
|
renderTicks = "0";
|
|
position = "0 10";
|
|
extent = "400 20";
|
|
minExtent = "8 2";
|
|
horizSizing = "right";
|
|
vertSizing = "center";
|
|
profile = GuiMenuButtonProfile;
|
|
visible = "1";
|
|
active = "1";
|
|
command = "$thisControl.updateSliderValue();";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
hovertime = "1000";
|
|
isContainer = "0";
|
|
canSave = "1";
|
|
canSaveDynamicFields = "0";
|
|
class = "OptionsSliderEntrySlider";
|
|
internalName = "slider";
|
|
};
|
|
};
|
|
};
|
|
|
|
return %entry;
|
|
}
|
|
|
|
function OptionsSliderEntrySlider::updateSliderValue(%this)
|
|
{
|
|
//update settings value here
|
|
}
|
|
|
|
function OptionsMenuActionMapButton::onHighlighted(%this, %highlighted)
|
|
{
|
|
%container = %this.getParent();
|
|
%container-->actionName.profile = %highlighted ? MenuSubHeaderTextHighlighted : MenuSubHeaderText;
|
|
|
|
OptionsMenuSettingsScroll.scrollToObject(%container);
|
|
}
|
|
|
|
function addActionMapEntry(%actionMap, %device, %keyMap, %index, %description)
|
|
{
|
|
%entry = new GuiContainer() {
|
|
position = "0 0";
|
|
extent = "800 40";
|
|
profile = GuiMenuDefaultProfile;
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
horizSizing = "width";
|
|
vertSizing = "bottom";
|
|
class = "OptionsKeybindEntry";
|
|
canSave = "0";
|
|
actionMap = %actionMap;
|
|
device = %device;
|
|
keymap = %keyMap;
|
|
remapIndex = %index;
|
|
|
|
new GuiButtonCtrl() {
|
|
profile = GuiMenuButtonProfile;
|
|
position = "0 0";
|
|
extent = "800 40";
|
|
horizSizing = "width";
|
|
vertSizing = "height";
|
|
internalName = "button";
|
|
class = "OptionsMenuActionMapButton";
|
|
altCommand = "doKeyRemap($thisControl.getParent());";
|
|
};
|
|
|
|
new GuiTextCtrl() {
|
|
text = getField(%keyMap, 0);
|
|
position = $optionsEntryPad SPC -1;
|
|
extent = "400 40";
|
|
profile = "MenuSubHeaderText";
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
internalName = "actionName";
|
|
};
|
|
|
|
new GuiContainer() {
|
|
position = "400 3";
|
|
extent = "400 34";
|
|
profile = GuiModelessDialogProfile;
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
horizSizing = "left";
|
|
vertSizing = "height";
|
|
internalName = "valuesContainer";
|
|
|
|
new GuiIconButtonCtrl() {
|
|
position = "300 -10";
|
|
extent = "98 45";
|
|
BitmapAsset = "";
|
|
profile = GuiRemapActionMapButtonProfile;
|
|
sizeIconToButton = true;
|
|
makeIconSquare = true;
|
|
iconLocation = "center";
|
|
internalName = "bindButton";
|
|
active = false;
|
|
};
|
|
};
|
|
};
|
|
|
|
return %entry;
|
|
} |