mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
1097 lines
37 KiB
Plaintext
1097 lines
37 KiB
Plaintext
//options settings
|
|
|
|
//Screen and Display menu
|
|
//Renderer Mode
|
|
//Screen resolution
|
|
//Windowed/fullscreen(borderless?)
|
|
//VSync
|
|
|
|
//Screen brightness
|
|
//screen brightness
|
|
//screen gamma
|
|
|
|
//Lighting Menu
|
|
//Shadow Distance(Distance shadows are drawn to. Also affects shadowmap slices)
|
|
//Shadow Quality(Resolution of shadows rendered, setting to none disables dynamic shadows)
|
|
//Soft Shadows(Whether shadow softening is used)
|
|
//Shadow caching(If the lights enable it, shadow caching is activated)
|
|
//Light Draw Distance(How far away lights are still drawn. Doesn't impact vector lights like the sun)
|
|
|
|
//Mesh and Textures Menu
|
|
//Draw distance(Overall draw distance) -slider
|
|
//Object draw distance(Draw distance from small/unimportant objects) -slider
|
|
//Mesh quality
|
|
//Texture quality
|
|
//Foliage draw distance
|
|
//Terrain Quality
|
|
//Decal Quality
|
|
|
|
//Effects Menu
|
|
//Parallax
|
|
//HDR
|
|
//Light shafts
|
|
//Motion Blur
|
|
//Depth of Field
|
|
//SSAO
|
|
//AA(ModelXAmount)[defualt is FXAA]
|
|
//Anisotropic filtering
|
|
|
|
//Keybinds
|
|
|
|
//Camera
|
|
//horizontal mouse sensitivity
|
|
//vert mouse sensitivity
|
|
//invert vertical
|
|
//zoom mouse sensitivities(both horz/vert)
|
|
//headbob
|
|
//FOV
|
|
|
|
$yesNoList = "No\tYes";
|
|
$onOffList = "Off\tOn";
|
|
|
|
function OptionsMenu::onAdd(%this)
|
|
{
|
|
if(!isObject(%this.optionsCategories))
|
|
{
|
|
%this.optionsCategories = new ArrayObject();
|
|
}
|
|
|
|
if(!isObject(%this.unappliedChanges))
|
|
{
|
|
%this.unappliedChanges = new ArrayObject(OptionsMenuUnappliedChanges);
|
|
}
|
|
|
|
%this.currentCategory = "";
|
|
|
|
addOptionsMenuCategory("Display", "populateDisplaySettingsList();");
|
|
addOptionsMenuCategory("Graphics", "populateGraphicsSettingsList();");
|
|
addOptionsMenuCategory("Audio", "populateAudioSettingsList();");
|
|
addOptionsMenuCategory("Keyboard & Mouse", "populateKeyboardMouseSettingsList();");
|
|
addOptionsMenuCategory("Gamepad", "populateGamepadSettingsList();");
|
|
|
|
callOnModules("populateOptionsMenuCategories", "Game");
|
|
}
|
|
|
|
function OptionsMenu::onOpen(%this)
|
|
{
|
|
OptionsMenuCategoryList.clear();
|
|
|
|
for(%i=0; %i < %this.optionsCategories.count(); %i++)
|
|
{
|
|
%catName = %this.optionsCategories.getKey(%i);
|
|
%callback = %this.optionsCategories.getValue(%i);
|
|
|
|
%newCatButton = new GuiButtonCtrl() {
|
|
text = %catName;
|
|
groupNum = "-1";
|
|
buttonType = "PushButton";
|
|
useMouseEvents = "0";
|
|
position = "0 180";
|
|
extent = "248 35";
|
|
minExtent = "8 2";
|
|
horizSizing = "right";
|
|
vertSizing = "bottom";
|
|
profile = "GuiMenuButtonProfile";
|
|
visible = "1";
|
|
active = "1";
|
|
command = %callback;
|
|
tooltipProfile = "GuiToolTipProfile";
|
|
hovertime = "1000";
|
|
isContainer = "0";
|
|
canSave = "1";
|
|
canSaveDynamicFields = "0";
|
|
};
|
|
|
|
OptionsMenuCategoryList.add(%newCatButton);
|
|
}
|
|
|
|
%this.unappliedChanges.empty();
|
|
|
|
OptionsMenuCategoryList.setAsActiveMenuList();
|
|
|
|
$activeMenuButtonContainer-->button1.set("btn_back", "R", "Reset", "OptionsMenu.resetToDefaults();");
|
|
$activeMenuButtonContainer-->button1.disable();
|
|
$activeMenuButtonContainer-->button3.set("", "Space", "Apply", "OptionsMenu.apply();");
|
|
$activeMenuButtonContainer-->button4.set("btn_a", "", "Select", "OptionsMenu.select();");
|
|
$activeMenuButtonContainer-->button5.set("btn_b", "Escape", "Back", %this @ ".navigation.popPage();");
|
|
}
|
|
|
|
//We capitalize on the canClose test here, because we want to prompt for unapplied options changes before
|
|
//backing out. So when the UINavigation test canClose, we can see if we have unapplied settings and prompt
|
|
//that via the message box and return false.
|
|
//This gives the user a chance to choose how they wish to proceed before we allow the
|
|
//UINavigation to move away from the options menu
|
|
function OptionsMenu::canClose(%this)
|
|
{
|
|
//Another special case is us catching the 'back/pop' action by just shifting from one
|
|
//menu list to another. In this case, we check if we were on the settings list as our active MenuList
|
|
//if so, then the back/pop just moves us to the Category list as our active and we inform the
|
|
//UINavigation to not close the page
|
|
if(OptionsMenuSettingsList.isActiveMenuList())
|
|
{
|
|
OptionsMenuCategoryList.setAsActiveMenuList();
|
|
%this.updateSelectButton();
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//Here, we're on the category list as our active, so we're actually trying to leae the page
|
|
//If we have unapplied changes, we want to prompt about them before closing the page and navigating away
|
|
//If we don't, then we can process the popPage as normal and let the OptionsMenu close
|
|
if(%this.unappliedChanges.count() != 0)
|
|
{
|
|
MessageBoxOKCancel("Discard Changes?", "You have unapplied changes to your settings, do you wish to apply or discard them?",
|
|
"OptionsMenu.apply(); MainMenuGUI.popPage();", "" @ %this @ ".unappliedChanges.empty(); " @ %this @ ".navigation.popPage();",
|
|
"Apply", "Discard");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function OptionsMenu::onClose(%this)
|
|
{
|
|
|
|
}
|
|
|
|
function OptionsMenuSettingsList::onAdd(%this)
|
|
{
|
|
}
|
|
|
|
function OptionsMenuSettingsList::getOptionsList(%this, %index)
|
|
{
|
|
}
|
|
|
|
function OptionsMenu::select(%this)
|
|
{
|
|
if(OptionsMenuCategoryList.isActiveMenuList())
|
|
{
|
|
OptionsMenuSettingsList.setAsActiveMenuList();
|
|
%this.updateSelectButton();
|
|
}
|
|
}
|
|
|
|
function OptionsMenu::updateSelectButton(%this)
|
|
{
|
|
if(OptionsMenuCategoryList.isActiveMenuList())
|
|
{
|
|
%this-->selectButton.setHidden(false);
|
|
}
|
|
else if(OptionsMenuSettingsList.isActiveMenuList())
|
|
{
|
|
%this-->selectButton.setHidden(true);
|
|
}
|
|
}
|
|
|
|
function OptionsMenu::apply(%this)
|
|
{
|
|
//Now we run through our list of unapplied changes and... apply them.
|
|
%hasKeybindChanges = false;
|
|
%hasVideoChanges = false;
|
|
%hasPostFXChanges = false;
|
|
%hasAudioChanges = false;
|
|
%hasGraphicsChanges = false;
|
|
for(%i=0; %i < %this.unappliedChanges.count(); %i++)
|
|
{
|
|
%targetVar = %this.unappliedChanges.getKey(%i);
|
|
%newValue = strReplace(%this.unappliedChanges.getValue(%i), "\"", "");
|
|
|
|
//First, lets just check through our action map names, see if any match
|
|
%wasKeybind = false;
|
|
for(%am=0; %am < ActionMapGroup.getCount(); %am++)
|
|
{
|
|
%actionMap = ActionMapGroup.getObject(%am);
|
|
|
|
if(%actionMap == GlobalActionMap.getId())
|
|
continue;
|
|
|
|
%actionMapName = %actionMap.humanReadableName $= "" ? %actionMap.getName() : %actionMap.humanReadableName;
|
|
if(%actionMapName $= %targetVar)
|
|
{
|
|
%hasKeybindChanges = true;
|
|
%wasKeybind = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!%wasKeybind)
|
|
{
|
|
%sanitizedVar = strReplace(%targetVar, "[", "");
|
|
%sanitizedVar = strReplace(%sanitizedVar, "]", "");
|
|
%sanitizedVar = strReplace(%sanitizedVar, ",", "_");
|
|
%currentValue = getVariable(%sanitizedVar);
|
|
if(%currentValue !$= %newValue)
|
|
{
|
|
setVariable(%targetVar, %newValue);
|
|
|
|
//now, lets check for special cases that need additional handling
|
|
//for updates
|
|
if ( %targetVar $= "$pref::Video::displayDevice" )
|
|
{
|
|
schedule(32, 0, "MessageBoxOK", "Change requires restart", "Please restart the game for a display device change to take effect.");
|
|
}
|
|
else if(startsWith(%targetVar, "$pref::PostFX::"))
|
|
{
|
|
%hasPostFXChanges = true;
|
|
}
|
|
else if(startsWith(%targetVar, "$pref::Video::"))
|
|
{
|
|
%hasVideoChanges = true;
|
|
|
|
//if it's the resolution, it's possible we got the human-friendly
|
|
//version stored off. if so, reprocess into the usable state
|
|
if(%targetVar $= "$pref::Video::Resolution")
|
|
{
|
|
if(strpos(%newValue, " x ") != -1)
|
|
{
|
|
%newValue = strreplace(%newValue, " x ", " ");
|
|
setVariable(%targetVar, %newValue);
|
|
}
|
|
}
|
|
}
|
|
else if(startsWith(%targetVar, "$pref::SFX::"))
|
|
{
|
|
%hasAudioChanges = true;
|
|
}
|
|
else if(startsWith(%targetVar, "$pref::Graphics::"))
|
|
{
|
|
%hasGraphicsChanges = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//If we had keybind changes, go ahead and save those out
|
|
if(%hasKeybindChanges)
|
|
{
|
|
%prefPath = getPrefpath();
|
|
|
|
%actionMapCount = ActionMapGroup.getCount();
|
|
|
|
%actionMapList = "";
|
|
%append = false;
|
|
for(%i=0; %i < %actionMapCount; %i++)
|
|
{
|
|
%actionMap = ActionMapGroup.getObject(%i);
|
|
|
|
if(%actionMap == GlobalActionMap.getId())
|
|
continue;
|
|
|
|
%actionMap.save( %prefPath @ "/keybinds." @ $TorqueScriptFileExtension, %append );
|
|
|
|
if(%append != true)
|
|
%append = true;
|
|
}
|
|
}
|
|
|
|
if(%hasPostFXChanges)
|
|
{
|
|
updatePostFXSettings();
|
|
}
|
|
|
|
if(%hasVideoChanges)
|
|
{
|
|
updateDisplaySettings();
|
|
}
|
|
|
|
if(%hasAudioChanges)
|
|
{
|
|
updateAudioSettings();
|
|
}
|
|
|
|
if(%hasGraphicsChanges)
|
|
{
|
|
updateGraphicsSettings();
|
|
}
|
|
|
|
//Finally, write our prefs to file
|
|
%prefPath = getPrefpath();
|
|
export("$pref::*", %prefPath @ "/clientPrefs." @ $TorqueScriptFileExtension, false);
|
|
|
|
OptionsMenu.unappliedChanges.empty();
|
|
}
|
|
|
|
function OptionsMenu::resetToDefaults(%this)
|
|
{
|
|
MessageBoxOKCancel("", "This will set the graphical settings back to the auto-detected defaults. Do you wish to continue?", "AutodetectGraphics();", "");
|
|
}
|
|
|
|
function OptionsMenu::refresh(%this)
|
|
{
|
|
%cat = %this.currentCategory;
|
|
if(%this.currentCategory !$= "")
|
|
{
|
|
if(!isInt(%this.currentCategory))
|
|
{
|
|
%this.currentCategory = getOptionsCategoryIndexByName(%this.currentCategory);
|
|
}
|
|
|
|
if(%this.currentCategory == -1)
|
|
return;
|
|
|
|
%category = %this.optionsCategories.getKey(%this.currentCategory);
|
|
%command = %this.optionsCategories.getValue(%this.currentCategory);
|
|
eval(%command);
|
|
}
|
|
|
|
//now, because we reconstruct the displayed set, we'll force the mouse(if we're using it as our input)
|
|
//to be poked so we can re-track to whatever control, if any, we're over
|
|
if($activeControllerType !$= "gamepad")
|
|
{
|
|
Canvas.setCursorPos(Canvas.getCursorPos());
|
|
}
|
|
}
|
|
|
|
function OptionsMenu::getOptionVariableValue(%this, %variableName)
|
|
{
|
|
%unappliedPrefIndex = %this.unappliedChanges.getIndexFromKey(%variableName);
|
|
if(%unappliedPrefIndex != -1)
|
|
{
|
|
%value = %this.unappliedChanges.getValue(%unappliedPrefIndex);
|
|
return strreplace(%value, "\"", "");
|
|
}
|
|
|
|
%sanitizedVar = strReplace(%variableName, "[", "");
|
|
%sanitizedVar = strReplace(%sanitizedVar, "]", "");
|
|
%sanitizedVar = strReplace(%sanitizedVar, ",", "_");
|
|
return getVariable(%sanitizedVar);
|
|
}
|
|
|
|
function OptionsMenuSelectButton::onVisible(%this, %state)
|
|
{
|
|
//We're sorta cheating here.
|
|
//This button should only be displayed when we're in the categories list
|
|
//so whenever the status changes, such as automatically refreshing due to
|
|
//navigation events, we'll just do a quick check to ensure we're
|
|
//in the right visibility mode
|
|
if(%state && OptionsMenuSettingsList.isActiveMenuList())
|
|
{
|
|
%this.setHidden(true);
|
|
}
|
|
}
|
|
//
|
|
//
|
|
//
|
|
function populateDisplaySettingsList()
|
|
{
|
|
OptionsMenuSettingsList.clear();
|
|
|
|
OptionsMenu.currentCategory = "Display";
|
|
|
|
if(isObject(OptionName))
|
|
OptionName.setText("");
|
|
if(isObject(OptionDescription))
|
|
OptionDescription.setText("");
|
|
|
|
%apiList = "";
|
|
%apiCount = GFXInit::getAdapterCount();
|
|
%apiIdx = 0;
|
|
for(%i=0; %i < %apiCount; %i++)
|
|
{
|
|
%api = GFXInit::getAdapterType(%i);
|
|
|
|
if(%api !$= "NullDevice")
|
|
{
|
|
if(%apiIdx==0)
|
|
%apiList = %api;
|
|
else
|
|
%apiList = %apiList TAB %api;
|
|
|
|
%apiIdx++;
|
|
}
|
|
}
|
|
|
|
trim(%apiList);
|
|
|
|
%displayDevice = OptionsMenu.getOptionVariableValue("$pref::Video::displayDevice");
|
|
if(%displayDevice $= "")
|
|
%displayDevice = getDisplayDeviceType();
|
|
|
|
OptionsMenuSettingsList.addOptionRow("Display API", "$pref::Video::displayDevice", %apiList, false, "", true, "The display API used for rendering.", %displayDevice);
|
|
|
|
%numDevices = Canvas.getMonitorCount();
|
|
%devicesList = "";
|
|
for(%i = 0; %i < %numDevices; %i++)
|
|
{
|
|
%device = (%i+1) @ " - " @ Canvas.getMonitorName(%i);
|
|
if(%i==0)
|
|
%devicesList = %device;
|
|
else
|
|
%devicesList = %devicesList @ "\t" @ %device;
|
|
}
|
|
|
|
%selectedDevice = getField(%devicesList, $pref::Video::deviceId);
|
|
OptionsMenuSettingsList.addOptionRow("Display Device", "$pref::Video::deviceId", %devicesList, false, "", true, "The display devices the window should be on.", %selectedDevice);
|
|
|
|
if (%numDevices > 1)
|
|
OptionsMenuSettingsList.setRowEnabled(1, true);
|
|
else
|
|
OptionsMenuSettingsList.setRowEnabled(1, false);
|
|
|
|
%mode = OptionsMenu.getOptionVariableValue("$pref::Video::deviceMode");
|
|
if(isInt(%mode))
|
|
%mode = getField($Video::ModeTags, $pref::Video::deviceMode);
|
|
OptionsMenuSettingsList.addOptionRow("Window Mode", "$pref::Video::deviceMode", $Video::ModeTags, false, "", true, "", %mode);
|
|
|
|
if(%mode !$= "Borderless")
|
|
{
|
|
%resolutionList = getScreenResolutionList($pref::Video::deviceId, $pref::Video::deviceMode);
|
|
%resolution = OptionsMenu.getOptionVariableValue("$pref::Video::Resolution");
|
|
if(%resolution $= "")
|
|
%resolution = $pref::Video::mode;
|
|
|
|
%resolution = _makePrettyResString(%resolution);
|
|
|
|
OptionsMenuSettingsList.addOptionRow("Resolution", "$pref::Video::Resolution", %resolutionList, false, "", true, "Resolution of the game window", %resolution);
|
|
}
|
|
|
|
OptionsMenuSettingsList.addOptionBoolRow("VSync", "$pref::Video::disableVerticalSync", $yesNoList, false, "", true, "");
|
|
|
|
|
|
%refreshList = getScreenRefreshList($pref::Video::mode);
|
|
OptionsMenuSettingsList.addOptionRow("Refresh Rate", "$pref::Video::RefreshRate", %refreshList, false, "", true, "", OptionsMenu.getOptionVariableValue("$pref::Video::RefreshRate"));
|
|
|
|
//move to gameplay tab
|
|
//OptionsMenuSettingsList.addSliderRow("Field of View", "", 75, 5, "65 100", "");
|
|
|
|
//OptionsMenuSettingsList.addSliderRow("Brightness", "", 0.5, 0.1, "0 1", "");
|
|
//OptionsMenuSettingsList.addSliderRow("Contrast", "", 0.5, 0.1, "0 1", "");
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
function populateGraphicsSettingsList()
|
|
{
|
|
OptionsMenuSettingsList.clear();
|
|
|
|
OptionsMenu.currentCategory = "Graphics";
|
|
|
|
if(isObject(OptionName))
|
|
OptionName.setText("");
|
|
if(isObject(OptionDescription))
|
|
OptionDescription.setText("");
|
|
|
|
%yesNoList = "No\tYes";
|
|
%onOffList = "Off\tOn";
|
|
%anisoFilter = "Off\t4\t8\t16";
|
|
%aaFilter = "Off\t1\t2\t4";
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Lighting Quality", "$pref::Graphics::LightingQuality",
|
|
LightingQualityList, false, "", true, "Amount and drawdistance of local lights");
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Shadow Quality", "$pref::Graphics::ShadowQuality",
|
|
ShadowQualityList, false, "", true, "Shadow revolution quality");
|
|
|
|
%shadowQuality = OptionsMenu.getOptionVariableValue("$pref::Graphics::ShadowQuality");
|
|
if(%shadowQuality !$= "None")
|
|
{
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Soft Shadow Quality", "$pref::Graphics::SoftShadowQuality",
|
|
SoftShadowList, false, "", true, "Amount of softening applied to shadowmaps");
|
|
}
|
|
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Mesh Quality", "$pref::Graphics::MeshQuality",
|
|
MeshQualityGroup, false, "", true, "Fidelity of rendering of mesh objects");
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Object Draw Distance", "$pref::Graphics::ObjectDrawDistance",
|
|
MeshDrawDistQualityGroup, false, "", true, "Dictates if and when static objects fade out in the distance");
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Texture Quality", "$pref::Graphics::TextureQuality",
|
|
TextureQualityGroup, false, "", true, "Fidelity of textures");
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Terrain Quality", "$pref::Graphics::TerrainQuality",
|
|
TerrainQualityGroup, false, "", true, "Quality level of terrain objects");
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Decal Lifetime", "$pref::Graphics::DecalLifetime",
|
|
DecalLifetimeGroup, false, "", true, "How long decals are rendered");
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Ground Cover Density", "$pref::Graphics::GroundCoverDensity",
|
|
GroundCoverDensityGroup, false, "", true, "Density of ground cover items, such as grass");
|
|
OptionsMenuSettingsList.addOptionQualityLevelRow("Shader Quality", "$pref::Graphics::ShaderQuality",
|
|
ShaderQualityGroup, false, "", true, "Dictates the overall shader quality level, adjusting what features are enabled.");
|
|
OptionsMenuSettingsList.addOptionRow("Anisotropic Filtering", "$pref::Video::defaultAnisotropy", %anisoFilter, false, "", true, "Amount of Anisotropic Filtering on textures, which dictates their sharpness at a distance");
|
|
OptionsMenuSettingsList.addOptionRow("Anti-Aliasing", "$pref::Video::AA", %aaFilter, false, "", true, "Amount of Post-Processing Anti-Aliasing applied to rendering");
|
|
OptionsMenuSettingsList.addOptionBoolRow("Parallax", "$pref::Video::disableParallaxMapping", %onOffList, false, "", true, "Whether the surface parallax shader effect is enabled");
|
|
OptionsMenuSettingsList.addOptionBoolRow("Water Reflections", "$pref::Water::disableTrueReflections", %onOffList, false, "", true, "Whether water reflections are enabled");
|
|
OptionsMenuSettingsList.addOptionBoolRow("SSAO", "$pref::PostFX::EnableSSAO", %onOffList, false, "", true, "Whether Screen-Space Ambient Occlusion is enabled");
|
|
OptionsMenuSettingsList.addOptionBoolRow("Depth of Field", "$pref::PostFX::EnableDOF", %onOffList, false, "", true, "Whether the Depth of Field effect is enabled");
|
|
OptionsMenuSettingsList.addOptionBoolRow("Vignette", "$pref::PostFX::EnableVignette", %onOffList, false, "", true, "Whether the vignette effect is enabled");
|
|
OptionsMenuSettingsList.addOptionBoolRow("Light Rays", "$pref::PostFX::EnableLightRays", %onOffList, false, "", true, "Whether the light rays effect is enabled");
|
|
}
|
|
|
|
function updateGraphicsSettings()
|
|
{
|
|
if($pref::Graphics::LightingQuality !$= getCurrentQualityLevel(LightingQualityList))
|
|
LightingQualityList.applySetting($pref::Graphics::LightingQuality);
|
|
if($pref::Graphics::ShadowQuality !$= getCurrentQualityLevel(ShadowQualityList))
|
|
ShadowQualityList.applySetting($pref::Graphics::ShadowQuality);
|
|
if($pref::Graphics::SoftShadowQuality !$= getCurrentQualityLevel(SoftShadowList))
|
|
SoftShadowList.applySetting($pref::Graphics::SoftShadowQuality);
|
|
|
|
if($pref::Graphics::MeshQuality !$= getCurrentQualityLevel(MeshQualityGroup))
|
|
MeshQualityGroup.applySetting($pref::Graphics::MeshQuality);
|
|
if($pref::Graphics::ObjectDrawDistance !$= getCurrentQualityLevel(MeshDrawDistQualityGroup))
|
|
MeshDrawDistQualityGroup.applySetting($pref::Graphics::ObjectDrawDistance);
|
|
if($pref::Graphics::TextureQuality !$= getCurrentQualityLevel(TextureQualityGroup))
|
|
{
|
|
TextureQualityGroup.applySetting($pref::Graphics::TextureQuality);
|
|
|
|
reloadTextures();
|
|
}
|
|
if($pref::Graphics::TerrainQuality !$= getCurrentQualityLevel(TerrainQualityGroup))
|
|
TerrainQualityGroup.applySetting($pref::Graphics::TerrainQuality);
|
|
if($pref::Graphics::DecalLifetime !$= getCurrentQualityLevel(DecalLifetimeGroup))
|
|
DecalLifetimeGroup.applySetting($pref::Graphics::DecalLifetime);
|
|
if($pref::Graphics::GroundCoverDensity !$= getCurrentQualityLevel(GroundCoverDensityGroup))
|
|
GroundCoverDensityGroup.applySetting($pref::Graphics::GroundCoverDensity);
|
|
}
|
|
|
|
function updateDisplaySettings()
|
|
{
|
|
//Update the display settings now
|
|
%deviceName = getDisplayDeviceName();
|
|
%newDeviceID = getWord(%deviceName, 0) - 1;
|
|
|
|
if(!isInt($pref::Video::deviceMode))
|
|
{
|
|
//probably saved out as the mode name, so just translate it back
|
|
for(%i=0; %i < getFieldCount($Video::ModeTags); %i++)
|
|
{
|
|
if(getField($Video::ModeTags, %i) $= $pref::Video::deviceMode)
|
|
{
|
|
$pref::Video::deviceMode = %i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
%deviceModeName = getField($Video::ModeTags, $pref::Video::deviceMode);
|
|
%newDeviceMode = 0;
|
|
foreach$(%modeName in $Video::ModeTags)
|
|
{
|
|
if (%deviceModeName $= %modeName)
|
|
break;
|
|
else
|
|
%newDeviceMode++;
|
|
}
|
|
|
|
if($pref::Video::deviceMode == $Video::ModeBorderless)
|
|
{
|
|
//if we're changing to borderless, we swap to the full resolution of the desktop
|
|
$pref::Video::mode = Canvas.getBestCanvasRes($pref::Video::deviceId, $pref::Video::deviceMode);
|
|
|
|
$pref::Video::Resolution = $pref::Video::mode.x SPC $pref::Video::mode.y;
|
|
}
|
|
|
|
%newRes = $pref::Video::Resolution;
|
|
%newBpp = 32; // ... its not 1997 anymore.
|
|
%newFullScreen = %deviceModeName $= "Fullscreen" ? true : false;
|
|
%newRefresh = $pref::Video::RefreshRate;
|
|
%newVsync = !$pref::Video::disableVerticalSync;
|
|
%newFSAA = $pref::Video::AA;
|
|
|
|
// Build the final mode string.
|
|
%newMode = $pref::Video::Resolution SPC %newFullScreen SPC %newBpp SPC %newRefresh SPC %newFSAA;
|
|
|
|
// Change the video mode.
|
|
if ( %newMode !$= $pref::Video::mode || %newDeviceID != $pref::Video::deviceId ||
|
|
%newVsync != $pref::Video::disableVerticalSync || %newDeviceMode != $pref::Video::deviceMode)
|
|
{
|
|
//****Edge Case Hack
|
|
// If we're in fullscreen mode and switching to a different monitor at the
|
|
// same resolution and maintaining fullscreen, GFX...WindowTarget::resetMode()
|
|
// will early-out because there is no "mode change" and the monitor change
|
|
// will not get applied. Instead of modifying platform code, we're going to
|
|
// move onto the new monitor in borderless and immediately switch to FS.
|
|
if (%newFullScreen && $pref::Video::FullScreen &&
|
|
($pref::Video::Resolution $= %newRes) && ($pref::Video::deviceId != %newDeviceID))
|
|
{
|
|
$pref::Video::deviceId = %newDeviceID;
|
|
$pref::Video::deviceMode = $Video::ModeBorderless;
|
|
%tmpModeStr = Canvas.getMonitorMode(%newDeviceID, 0);
|
|
Canvas.setVideoMode(%tmpModeStr.x, %tmpModeStr.y, false, 32, getWord(%tmpModeStr, $WORD::REFRESH), %newFSAA);
|
|
}
|
|
|
|
$pref::Video::mode = %newMode;
|
|
$pref::Video::disableVerticalSync = %newVsync;
|
|
$pref::Video::deviceId = %newDeviceID;
|
|
$pref::Video::deviceMode = %newDeviceMode;
|
|
$pref::Video::Resolution = %newRes;
|
|
$pref::Video::FullScreen = %newFullScreen;
|
|
$pref::Video::RefreshRate = %newRefresh;
|
|
$pref::Video::AA = %newFSAA;
|
|
configureCanvas();
|
|
}
|
|
}
|
|
|
|
function updatePostFXSettings()
|
|
{
|
|
PostFXManager.settingsEffectSetEnabled(SSAOPostFx, $pref::PostFX::EnableSSAO);
|
|
PostFXManager.settingsEffectSetEnabled(DepthOfFieldPostFX, $pref::PostFX::EnableDOF);
|
|
PostFXManager.settingsEffectSetEnabled(LightRayPostFX, $pref::PostFX::EnableLightRays);
|
|
PostFXManager.settingsEffectSetEnabled(vignettePostFX, $pref::PostFX::EnableVignette);
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
function populateAudioSettingsList()
|
|
{
|
|
OptionsMenuSettingsList.clear();
|
|
|
|
OptionsMenu.currentCategory = "Audio";
|
|
|
|
if(isObject(OptionName))
|
|
OptionName.setText("");
|
|
if(isObject(OptionDescription))
|
|
OptionDescription.setText("");
|
|
|
|
%buffer = sfxGetAvailableDevices();
|
|
%count = getRecordCount( %buffer );
|
|
%audioDriverList = "";
|
|
%audioProviderList = "";
|
|
%audioDeviceList = "";
|
|
|
|
$currentAudioProvider = $currentAudioProvider $= "" ? $pref::SFX::provider : $currentAudioProvider;
|
|
|
|
for(%i = 0; %i < %count; %i++)
|
|
{
|
|
%record = getRecord(%buffer, %i);
|
|
%provider = getField(%record, 0);
|
|
%device = getField(%record, 1);
|
|
|
|
//When the client is actually running, we don't care about null audo devices
|
|
if(%provider $= "null")
|
|
continue;
|
|
|
|
if(%audioProviderList $= "")
|
|
%audioProviderList = %provider;
|
|
else
|
|
%audioProviderList = %audioProviderList @ "\t" @ %provider;
|
|
|
|
if(%provider $= $currentAudioProvider)
|
|
{
|
|
if(%audioDeviceList $= "")
|
|
%audioDeviceList = %device;
|
|
else
|
|
%audioDeviceList = %audioDeviceList @ "\t" @ %device;
|
|
}
|
|
}
|
|
|
|
OptionsMenuSettingsList.addOptionRow("Audio Provider", "$pref::SFX::AudioProvider", %audioProviderList, false, "audioProviderChanged", true, "");
|
|
OptionsMenuSettingsList.addOptionRow("Audio Device", "$pref::SFX::device", %audioDeviceList, false, "", true);
|
|
|
|
OptionsMenuSettingsList.addSliderRow("Master Volume", "$pref::SFX::masterVolume", 0.1, "0 1", "");
|
|
OptionsMenuSettingsList.addSliderRow("GUI Volume", "$pref::SFX::channelVolume[" @ $GuiAudioType @ "]", 0.1, "0 1", "");
|
|
OptionsMenuSettingsList.addSliderRow("Effects Volume", "$pref::SFX::channelVolume[" @ $SimAudioType @ "]", 0.1, "0 1", "");
|
|
OptionsMenuSettingsList.addSliderRow("Music Volume", "$pref::SFX::channelVolume[" @ $MusicAudioType @ "]", 0.1, "0 1", "");
|
|
}
|
|
|
|
function audioProviderChanged()
|
|
{
|
|
//Get the option we have set for the provider
|
|
%provider = OptionsMenuSettingsList.getCurrentOption(0);
|
|
$currentAudioProvider = %provider;
|
|
|
|
//And now refresh the list to get the correct devices
|
|
populateAudioSettingsList();
|
|
}
|
|
|
|
function updateAudioSettings()
|
|
{
|
|
//$pref::SFX::masterVolume = OptionsMenuSettingsList.getValue(2);
|
|
sfxSetMasterVolume( $pref::SFX::masterVolume );
|
|
|
|
//$pref::SFX::channelVolume[ $GuiAudioType ] = OptionsMenuSettingsList.getValue(3);
|
|
//$pref::SFX::channelVolume[ $SimAudioType ] = OptionsMenuSettingsList.getValue(4);
|
|
//$pref::SFX::channelVolume[ $MusicAudioType ] = OptionsMenuSettingsList.getValue(5);
|
|
|
|
sfxSetChannelVolume( $GuiAudioType, $pref::SFX::channelVolume[ $GuiAudioType ] );
|
|
sfxSetChannelVolume( $SimAudioType, $pref::SFX::channelVolume[ $SimAudioType ] );
|
|
sfxSetChannelVolume( $MusicAudioType, $pref::SFX::channelVolume[ $MusicAudioType ] );
|
|
|
|
//$pref::SFX::provider = OptionsMenuSettingsList.getCurrentOption(0);
|
|
//$pref::SFX::device = OptionsMenuSettingsList.getCurrentOption(1);
|
|
|
|
if ( !sfxCreateDevice( $pref::SFX::provider,
|
|
$pref::SFX::device,
|
|
$pref::SFX::useHardware,
|
|
-1 ) )
|
|
error( "Unable to create SFX device: " @ $pref::SFX::provider
|
|
SPC $pref::SFX::device
|
|
SPC $pref::SFX::useHardware );
|
|
|
|
if( !isObject( $AudioTestHandle ) )
|
|
{
|
|
sfxPlay(menuButtonPressed);
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
function populateKeyboardMouseSettingsList()
|
|
{
|
|
OptionsMenuSettingsList.clear();
|
|
|
|
OptionsMenu.currentCategory = "Keyboard & Mouse";
|
|
|
|
if(isObject(OptionName))
|
|
OptionName.setText("");
|
|
if(isObject(OptionDescription))
|
|
OptionDescription.setText("");
|
|
|
|
$remapListDevice = "keyboard";
|
|
fillRemapList();
|
|
|
|
//OptionsMenuSettingsList.refresh();
|
|
}
|
|
|
|
function populateGamepadSettingsList()
|
|
{
|
|
OptionsMenuSettingsList.clear();
|
|
|
|
OptionsMenu.currentCategory = "Gamepad";
|
|
|
|
if(isObject(OptionName))
|
|
OptionName.setText("");
|
|
if(isObject(OptionDescription))
|
|
OptionDescription.setText("");
|
|
|
|
$remapListDevice = "gamepad";
|
|
fillRemapList();
|
|
|
|
OptionsMenuSettingsList.updateStack();
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
function OptionsMenuList::activateRow(%this)
|
|
{
|
|
OptionsMenuSettingsList.setFirstResponder();
|
|
}
|
|
|
|
function OptionsMenuSettingsList::setRowEnabled(%this, %row, %status)
|
|
{
|
|
%option = %this.getObject(%row);
|
|
if(isObject(%option))
|
|
{
|
|
%option.setEnabled(%status);
|
|
}
|
|
}
|
|
|
|
function OptionsMenuSettingsList::addOptionRow(%this, %label, %targetPrefVar, %optionsList, %wrapOptions, %callback, %enabled, %description, %defaultValue)
|
|
{
|
|
if(%enabled $= "")
|
|
%enabled = true;
|
|
|
|
%optionsRowSize = 30;
|
|
%optionColumnWidth = %this.extent.x * 0.3;//todo, calculate off longest option text?
|
|
|
|
%option = new GuiGameSettingsCtrl() {
|
|
class = "MenuOptionsButton";
|
|
profile = "GuiMenuButtonProfile";
|
|
horizSizing = "width";
|
|
vertSizing = "bottom";
|
|
position = "0 0";
|
|
extent = %this.extent.x SPC %optionsRowSize;
|
|
columnSplit = %optionColumnWidth;
|
|
useMouseEvents = true;
|
|
previousBitmapAsset = "UI:previousOption_n_image";
|
|
nextBitmapAsset = "UI:nextOption_n_image";
|
|
};
|
|
|
|
%option.targetPrefVar = %targetPrefVar; //create a var-option association
|
|
|
|
%option.setListSetting(%label, %optionsList, %wrapOptions, %callback, %enabled, %description, %defaultValue);
|
|
|
|
%this.add(%option);
|
|
}
|
|
|
|
function OptionsMenuSettingsList::addOptionQualityLevelRow(%this, %label, %targetPrefVar, %qualityLevelList, %wrapOptions, %callback, %enabled, %description, %defaultValue)
|
|
{
|
|
if(%defaultValue $= "")
|
|
{
|
|
%unappliedPrefIndex = OptionsMenu.unappliedChanges.getIndexFromKey(%targetPrefVar);
|
|
if(%unappliedPrefIndex != -1)
|
|
{
|
|
%value = OptionsMenu.unappliedChanges.getValue(%unappliedPrefIndex);
|
|
%defaultValue = strreplace(%value, "\"", "");
|
|
}
|
|
|
|
if(%defaultValue $= "")
|
|
{
|
|
%sanitizedVar = strReplace(%targetPrefVar, "[", "");
|
|
%sanitizedVar = strReplace(%sanitizedVar, "]", "");
|
|
%sanitizedVar = strReplace(%sanitizedVar, ",", "_");
|
|
%defaultValue = getVariable(%sanitizedVar);
|
|
}
|
|
|
|
if(%defaultValue $= "")
|
|
%defaultValue = getCurrentQualityLevel(%qualityLevelList);
|
|
}
|
|
|
|
return %this.addOptionRow(%label, %targetPrefVar, getQualityLevels(%qualityLevelList),
|
|
%wrapOptions, %callback, %enabled, %description, %defaultValue);
|
|
}
|
|
|
|
function OptionsMenuSettingsList::addOptionBoolRow(%this, %label, %targetPrefVar, %qualityLevelList, %wrapOptions, %callback, %enabled, %description, %defaultValue)
|
|
{
|
|
if(%defaultValue $= "")
|
|
%defaultValue = OptionsMenu.getOptionVariableValue(%targetPrefVar);
|
|
|
|
if(%qualityLevelList $= $yesNoList && isInt(%defaultValue))
|
|
{
|
|
%defaultValue = convertBoolToYesNo(%defaultValue);
|
|
}
|
|
else if(%qualityLevelList $= $onOffList && isInt(%defaultValue))
|
|
{
|
|
%defaultValue = convertBoolToOnOff(%defaultValue);
|
|
}
|
|
|
|
return %this.addOptionRow(%label, %targetPrefVar, %qualityLevelList,
|
|
%wrapOptions, %callback, %enabled, %description, %defaultValue);
|
|
}
|
|
|
|
function OptionsMenuSettingsList::addSliderRow(%this, %label, %targetPrefVar, %increment, %range, %callback, %enabled, %description, %defaultValue)
|
|
{
|
|
if(%enabled $= "")
|
|
%enabled = true;
|
|
|
|
%optionsRowSize = 30;
|
|
%optionColumnWidth = %this.extent.x - 450;//todo, calculate off longest option text?
|
|
|
|
%option = new GuiGameSettingsCtrl() {
|
|
class = "MenuOptionsButton";
|
|
profile = "GuiMenuButtonProfile";
|
|
horizSizing = "width";
|
|
vertSizing = "bottom";
|
|
position = "0 0";
|
|
extent = %this.extent.x SPC %optionsRowSize;
|
|
columnSplit = %optionColumnWidth;
|
|
useMouseEvents = true;
|
|
};
|
|
|
|
%option.targetPrefVar = %targetPrefVar; //create a var-option association
|
|
|
|
if(%defaultValue $= "")
|
|
%defaultValue = OptionsMenu.getOptionVariableValue(%targetPrefVar);
|
|
|
|
%option.setSliderSetting(%label, %defaultValue, %increment, %range, %callback, %enabled, %description);
|
|
|
|
%this.add(%option);
|
|
}
|
|
|
|
function OptionsMenuSettingsList::addKeybindRow(%this, %label, %bitmapName, %callback, %enabled, %description)
|
|
{
|
|
if(%enabled $= "")
|
|
%enabled = true;
|
|
|
|
%optionsRowSize = 40;
|
|
%optionColumnWidth = %this.extent.x - 450;
|
|
|
|
%option = new GuiGameSettingsCtrl() {
|
|
class = "MenuOptionsButton";
|
|
profile = "GuiMenuButtonProfile";
|
|
horizSizing = "width";
|
|
vertSizing = "bottom";
|
|
position = "0 0";
|
|
extent = %this.extent.x SPC %optionsRowSize;
|
|
columnSplit = %optionColumnWidth;
|
|
useMouseEvents = true;
|
|
};
|
|
|
|
%option.setKeybindSetting(%label, %bitmapName, %callback, %enabled, %description);
|
|
|
|
%this.add(%option);
|
|
}
|
|
|
|
//
|
|
function OptionsMenuCategoryList::onNavigate(%this, %index)
|
|
{
|
|
OptionsMenu.currentCategory = %index;
|
|
%this.getObject(%index).performClick();
|
|
}
|
|
|
|
function convertOptionToBool(%val)
|
|
{
|
|
if(%val $= "yes" || %val $= "on")
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
function convertBoolToYesNo(%val)
|
|
{
|
|
if(%val == 1)
|
|
return "Yes";
|
|
else if(%val == 0)
|
|
return "No";
|
|
|
|
return %val;
|
|
}
|
|
|
|
function convertBoolToOnOff(%val)
|
|
{
|
|
if(%val == 1)
|
|
return "On";
|
|
else if(%val == 0)
|
|
return "Off";
|
|
|
|
return %val;
|
|
}
|
|
|
|
function getDisplayDeviceName()
|
|
{
|
|
%numDevices = Canvas.getMonitorCount();
|
|
%devicesList = "";
|
|
for(%i = 0; %i < %numDevices; %i++)
|
|
{
|
|
%device = (%i+1) @ " - " @ Canvas.getMonitorName(%i);
|
|
if(%i==0)
|
|
%devicesList = %device;
|
|
else
|
|
%devicesList = %devicesList @ "\t" @ %device;
|
|
}
|
|
|
|
return getField(%devicesList, $pref::Video::deviceId);
|
|
}
|
|
//
|
|
//
|
|
//
|
|
function MenuOptionsButton::onMouseEnter(%this)
|
|
{
|
|
if(isObject(OptionName))
|
|
OptionName.setText(%this.getLabel());
|
|
if(isObject(OptionDescription))
|
|
OptionDescription.setText(%this.getToolTip());
|
|
}
|
|
|
|
function MenuOptionsButton::onMouseLeave(%this)
|
|
{
|
|
if(isObject(OptionName))
|
|
OptionName.setText("");
|
|
if(isObject(OptionDescription))
|
|
OptionDescription.setText("");
|
|
}
|
|
|
|
function MenuOptionsButton::onHighlighted(%this, %state)
|
|
{
|
|
MenuListButton::onHighlighted(%this, %state);
|
|
}
|
|
|
|
function MenuOptionsButton::onChange(%this)
|
|
{
|
|
%optionMode = %this.getMode();
|
|
%optionName = %this.getLabel();
|
|
%tooltipText = %this.getTooltip();
|
|
|
|
%targetVar = %this.targetPrefVar;
|
|
|
|
OptionName.setText(%optionName);
|
|
OptionDescription.setText(%tooltipText);
|
|
|
|
if(%optionMode == 0)
|
|
{
|
|
%currentValue = %this.getCurrentOption();
|
|
if(%currentValue !$= "")
|
|
{
|
|
if(%currentValue $= "yes" || %currentValue $= "on")
|
|
%saveReadyValue = 1;
|
|
else if(%currentValue $= "no" || %currentValue $= "off")
|
|
%saveReadyValue = 0;
|
|
else
|
|
%saveReadyValue = %currentValue;
|
|
|
|
%prefIndex = OptionsMenu.unappliedChanges.getIndexFromKey(%targetVar);
|
|
if(%prefIndex == -1)
|
|
{
|
|
echo("Setting UnappliedChanges via add: key:" @ %targetVar @", value: " @ %saveReadyValue);
|
|
OptionsMenu.unappliedChanges.add(%targetVar, "\"" @ %saveReadyValue @ "\"" );
|
|
}
|
|
else
|
|
{
|
|
OptionsMenu.unappliedChanges.setValue("\"" @ %saveReadyValue @ "\"", %prefIndex);
|
|
}
|
|
}
|
|
}
|
|
else if(%optionMode == 1)
|
|
{
|
|
%currentValue = %this.getValue();
|
|
|
|
%prefIndex = OptionsMenu.unappliedChanges.getIndexFromKey(%targetVar);
|
|
if(%prefIndex == -1)
|
|
{
|
|
echo("Setting UnappliedChanges via add: key:" @ %targetVar @", value: " @ %currentValue);
|
|
OptionsMenu.unappliedChanges.add(%targetVar, "\"" @ %currentValue @ "\"" );
|
|
}
|
|
else
|
|
{
|
|
OptionsMenu.unappliedChanges.setValue("\"" @ %currentValue @ "\"", %prefIndex);
|
|
}
|
|
}
|
|
|
|
//Update the UI in case there's responsive logic
|
|
OptionsMenu.schedule(32, "refresh");
|
|
}
|
|
|
|
function OptionsMenu::onKeybindChanged(%this, %actionMap, %keybind)
|
|
{
|
|
%prefIndex = OptionsMenu.unappliedChanges.getIndexFromKey(%actionMap);
|
|
if(%prefIndex == -1)
|
|
OptionsMenu.unappliedChanges.add(%actionMap, %keybind);
|
|
else
|
|
OptionsMenu.unappliedChanges.setValue(%keybind, %prefIndex);
|
|
}
|
|
|
|
//
|
|
// Indicates what category the options item should be added into
|
|
//
|
|
function addOptionsMenuCategory(%categoryName, %selectCallback)
|
|
{
|
|
//Don't add duplicates!
|
|
%index = OptionsMenu.optionsCategories.getIndexFromKey(%categoryName);
|
|
if(%index == -1)
|
|
OptionsMenu.optionsCategories.add(%categoryName, %selectCallback);
|
|
}
|
|
|
|
function removeOptionsMenuCategory(%categoryName)
|
|
{
|
|
%index = OptionsMenu.optionsCategories.getIndexFromKey(%categoryName);
|
|
if(%index != -1)
|
|
OptionsMenu.optionsCategories.erase(%index);
|
|
}
|
|
|
|
function getOptionsCategoryIndexByName(%categoryName)
|
|
{
|
|
for(%i=0; %i < OptionsMenu.optionsCategories.count(); %i++)
|
|
{
|
|
if(OptionsMenu.optionsCategories.getKey(%i) $= %categoryName)
|
|
return %i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
function addListOption(%label, %description, %targetPrefVar, %optionsList, %wrapOptions, %callback, %enabled)
|
|
{
|
|
if(%wrapOptions $= "")
|
|
%wrapOptions = false;
|
|
|
|
if(%enabled $= "")
|
|
%enabled = true;
|
|
|
|
OptionsMenuSettingsList.addOptionRow(%label, %targetPrefVar, %optionsList, %wrapOptions, %callback, %enabled, %description, %targetPrefVar);
|
|
}
|
|
|
|
function addSliderOption(%label, %description, %targetPrefVar, %defaultValue, %increment, %range, %callback, %enabled)
|
|
{
|
|
if(%enabled $= "")
|
|
%enabled = true;
|
|
|
|
OptionsMenuSettingsList.addSliderRow(%label, %targetPrefVar, %defaultValue, %increment, %range, %callback, %enabled, %description);
|
|
}
|
|
|
|
function addKeybindOption(%label, %description, %bitmapName, %callback, %enabled)
|
|
{
|
|
if(%enabled $= "")
|
|
%enabled = true;
|
|
|
|
OptionsMenuSettingsList.addSliderRow(%label, %bitmapName, %callback, %enabled, %description);
|
|
}
|