Updated version of OTHGMars' updated window and resolution options modes.

Additional changes include disabling certain options when they are not valid(ie, resolution is disabled when in borderless mode)
This commit is contained in:
Areloch 2020-09-20 02:06:15 -05:00
parent d76c73c252
commit 26ef40950b
12 changed files with 559 additions and 152 deletions

View file

@ -533,6 +533,14 @@ void GuiGameListMenuCtrl::addRow(const char* label, const char* bitmapName, cons
addRow(row, label, callback, icon, yPad, true, enabled, Row::Mode::Keybind, tooltip);
}
void GuiGameListMenuCtrl::removeRow(const S32& row)
{
if (row == -1 || row >= mRows.size())
return;
mRows.erase(row);
}
Point2I GuiGameListMenuCtrl::getMinExtent() const
{
Point2I parentMin = Parent::getMinExtent();
@ -1521,6 +1529,12 @@ DefineEngineMethod(GuiGameListMenuCtrl, addKeybindRow, void,
object->addRow(label, bitmapName, callback, icon, yPad, enabled, tooltip);
}
DefineEngineMethod(GuiGameListMenuCtrl, removeRow, void, (S32 row),,
"Removes the row at the provided index")
{
object->removeRow(row);
}
DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOption, const char*, (S32 row), ,
"Gets the text for the currently selected option of the given row.\n\n"
"@param row Index of the row to get the option from.\n"

View file

@ -163,6 +163,9 @@ public:
void addRow(const char* label, const char* bitmapName, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip);
//Removes row at the provided index
void GuiGameListMenuCtrl::removeRow(const S32& row);
/// Gets the text for the currently selected option of the given row.
///
/// \param rowIndex Index of the row to get the option from.

View file

@ -238,7 +238,8 @@ bool GuiCanvas::onAdd()
mPlatformWindow->lockSize(true);
// Set a minimum on the window size so people can't break us by resizing tiny.
mPlatformWindow->setMinimumWindowSize(Point2I(640,480));
mPlatformWindow->setMinimumWindowSize(Point2I(Con::getIntVariable("$Video::minimumXResolution", 1024),
Con::getIntVariable("$Video::minimumYResolution", 720)));
// Now, we have to hook in our event callbacks so we'll get
// appropriate events from the window.
@ -2462,6 +2463,35 @@ DefineEngineMethod( GuiCanvas, getMonitorRect, RectI, (S32 index),,
return PlatformWindowManager::get()->getMonitorRect(index);
}
DefineEngineMethod( GuiCanvas, getMonitorUsableRect, RectI, (S32 index),,
"@brief Use this function to get the usable desktop area represented by a display, with the primary display located at 0,0.\n\n"
"This is the same area as Canvas.getMonitorRect() reports, but with portions reserved by the system removed. "
"For example, on Apple Mac OS X, this subtracts the area occupied by the menu bar and dock.\n"
"Setting a window to be fullscreen generally bypasses these unusable areas, so these are good guidelines for "
"the maximum space available to a non - fullscreen window."
"@param index The monitor index.\n\n"
"@return The rectangular region of the requested monitor.")
{
return PlatformWindowManager::get()->getMonitorUsableRect(index);
}
DefineEngineMethod(GuiCanvas, getMonitorModeCount, S32, (S32 monitorIndex), (0),
"Gets the number of video modes available on the selected monitor.\n\n")
{
return PlatformWindowManager::get()->getMonitorModeCount(monitorIndex);
}
DefineEngineMethod(GuiCanvas, getMonitorMode, const char*, (S32 monitorIndex, S32 modeIndex), (0),
"Gets a video mode string from the selected monitor.\n\n")
{
char* buf = Con::getReturnBuffer(PlatformWindowManager::get()->getMonitorMode(monitorIndex, modeIndex));
return buf;
}
DefineEngineMethod(GuiCanvas, getMonitorDesktopMode, const char*, (S32 monitorIndex), (0),
"Gets the current desktop mode for the selected monitor.\n\n")
{
char* buf = Con::getReturnBuffer(PlatformWindowManager::get()->getMonitorDesktopMode(monitorIndex));
return buf;
}
DefineEngineMethod( GuiCanvas, getVideoMode, const char*, (),,
"@brief Gets the current screen mode as a string.\n\n"
@ -2698,8 +2728,11 @@ DefineEngineMethod( GuiCanvas, restoreWindow, void, (), , "() - restore this can
DefineEngineMethod( GuiCanvas, setFocus, void, (), , "() - Claim OS input focus for this canvas' window.")
{
PlatformWindow* window = object->getPlatformWindow();
if( window )
if (window)
{
window->setFocus();
window->appEvent.trigger(window->getWindowId(), GainFocus);
}
}
DefineEngineMethod( GuiCanvas, setMenuBar, void, ( GuiControl* menu ),,

View file

@ -90,6 +90,23 @@ public:
// Get the requested monitor's rectangular region.
virtual RectI getMonitorRect(U32 index) { return RectI(0, 0, 0, 0); }
// Get the requested monitor's rectangular region.
// Use this function to get the usable desktop area represented by a display,
// with the primary display located at 0,0.
virtual RectI getMonitorUsableRect(U32 index) { return RectI(0, 0, 0, 0); }
// Retrieve the number of display modes available on a monitor. Provides a default
// count of 0 for systems that don't provide information on connected monitors.
virtual U32 getMonitorModeCount(U32 monitorIndex) { return 0; }
// Gets a display mode for a specific monitor. Provides a default of "" for platorms
// that do not provide information on connected monitors.
virtual const String getMonitorMode(U32 monitorIndex, U32 modeIndex) { return String::EmptyString; }
// Gets the current desktop display mode for a specific monitor. Provides a default
// of "" for platorms that do not provide information on connected monitors.
virtual const String getMonitorDesktopMode(U32 monitorIndex) { return String::EmptyString; }
/// Populate a vector with all monitors and their extents in window space.
virtual void getMonitorRegions(Vector<RectI> &regions) = 0;
@ -152,4 +169,4 @@ private:
/// need to get the window manager from somewhere else.
PlatformWindowManager *CreatePlatformWindowManager();
#endif
#endif

View file

@ -161,10 +161,18 @@ void PlatformWindowSDL::_setVideoMode( const GFXVideoMode &mode )
{
mVideoMode = mode;
mSuppressReset = true;
S32 newDisplay = Con::getIntVariable("pref::Video::deviceId", 0);
// Set our window to have the right style based on the mode
if(mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender)
{
{
SDL_Rect rect_sdl;
// Move the window onto the correct monitor before setting fullscreen
if (0 == SDL_GetDisplayBounds(newDisplay, &rect_sdl))
{
SDL_SetWindowPosition(mWindowHandle, rect_sdl.x, rect_sdl.y);
}
setSize(mode.resolution);
SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
@ -187,10 +195,19 @@ void PlatformWindowSDL::_setVideoMode( const GFXVideoMode &mode )
SDL_SetWindowFullscreen( mWindowHandle, 0);
}
// Restore the window to it's original size/position before applying changes
SDL_RestoreWindow(mWindowHandle);
// pref::Video::deviceMode values 0-windowed, 1-borderless, 2-fullscreen
bool hasBorder = (0 == Con::getIntVariable("pref::Video::deviceMode", 0));
SDL_SetWindowBordered(mWindowHandle, hasBorder ? SDL_TRUE : SDL_FALSE);
setSize(mode.resolution);
centerWindow();
SDL_SetWindowPosition(mWindowHandle, SDL_WINDOWPOS_CENTERED_DISPLAY(newDisplay), SDL_WINDOWPOS_CENTERED_DISPLAY(newDisplay));
if (hasBorder && Con::getBoolVariable("pref::Video::isMaximized", false))
SDL_MaximizeWindow(mWindowHandle);
}
getScreenResChangeSignal().trigger(this, true);
mSuppressReset = false;
}
@ -216,7 +233,7 @@ void PlatformWindowSDL::_setFullscreen(const bool fullscreen)
if(fullscreen && !mOffscreenRender)
{
Con::printf("PlatformWindowSDL::setFullscreen (full) enter");
SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
}
else
{
@ -245,7 +262,7 @@ const char * PlatformWindowSDL::getCaption()
void PlatformWindowSDL::setFocus()
{
SDL_SetWindowInputFocus(mWindowHandle);
SDL_RaiseWindow(mWindowHandle);
}
void PlatformWindowSDL::setClientExtent( const Point2I newExtent )
@ -322,11 +339,6 @@ void PlatformWindowSDL::centerWindow()
bool PlatformWindowSDL::setSize( const Point2I &newSize )
{
SDL_SetWindowSize(mWindowHandle, newSize.x, newSize.y);
// Let GFX get an update about the new resolution
if (mTarget.isValid())
mTarget->resetMode();
return true;
}
@ -475,6 +487,12 @@ void PlatformWindowSDL::_triggerMouseButtonNotify(const SDL_Event& event)
case SDL_BUTTON_MIDDLE:
button = 2;
break;
case SDL_BUTTON_X1:
button = 3;
break;
case SDL_BUTTON_X2:
button = 4;
break;
default:
return;
}
@ -547,6 +565,24 @@ void PlatformWindowSDL::_triggerTextNotify(const SDL_Event& evt)
}
}
void PlatformWindowSDL::_updateMonitorFromMove(const SDL_Event& evt)
{
SDL_Rect sdlRect;
S32 monitorCount = SDL_GetNumVideoDisplays();
for (S32 index = 0; index < monitorCount; ++index)
{
if (0 == SDL_GetDisplayBounds(index, &sdlRect))
{
if ((evt.window.data1 >= sdlRect.x) && (evt.window.data1 < (sdlRect.x + sdlRect.w)) &&
(evt.window.data2 >= sdlRect.y) && (evt.window.data2 < (sdlRect.y + sdlRect.h)))
{
Con::setIntVariable("pref::Video::deviceId", index);
return;
}
}
}
}
void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
{
switch(evt.type)
@ -594,7 +630,11 @@ void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
case SDL_WINDOWEVENT_FOCUS_LOST:
appEvent.trigger(getWindowId(), LoseFocus);
break;
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_MOVED:
{
_updateMonitorFromMove(evt);
break;
}
case SDL_WINDOWEVENT_RESIZED:
{
int width, height;
@ -602,6 +642,7 @@ void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
mVideoMode.resolution.set(width, height);
getGFXTarget()->resetMode();
resizeEvent.trigger(getWindowId(), width, height);
getScreenResChangeSignal().trigger(this, true);
break;
}
case SDL_WINDOWEVENT_CLOSE:
@ -609,6 +650,14 @@ void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
appEvent.trigger(getWindowId(), WindowClose);
mClosing = true;
}
case SDL_WINDOWEVENT_MINIMIZED:
break;
case SDL_WINDOWEVENT_MAXIMIZED:
Con::setBoolVariable("pref::Video::isMaximized", true);
break;
case SDL_WINDOWEVENT_RESTORED:
Con::setBoolVariable("pref::Video::isMaximized", false);
break;
default:
break;

View file

@ -98,6 +98,7 @@ private:
void _triggerMouseWheelNotify(const SDL_Event& event);
void _triggerKeyNotify(const SDL_Event& event);
void _triggerTextNotify(const SDL_Event& event);
void _updateMonitorFromMove(const SDL_Event& event);
public:
PlatformWindowSDL();

View file

@ -143,6 +143,74 @@ RectI PlatformWindowManagerSDL::getMonitorRect(U32 index)
return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h);
}
RectI PlatformWindowManagerSDL::getMonitorUsableRect(U32 index)
{
SDL_Rect sdlRect;
if (0 != SDL_GetDisplayUsableBounds(index, &sdlRect))
{
Con::errorf("SDL_GetDisplayUsableBounds() failed: %s", SDL_GetError());
return RectI(0, 0, 0, 0);
}
return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h);
}
U32 PlatformWindowManagerSDL::getMonitorModeCount(U32 monitorIndex)
{
S32 modeCount = SDL_GetNumDisplayModes(monitorIndex);
if (modeCount < 0)
{
Con::errorf("SDL_GetNumDisplayModes(%d) failed: %s", monitorIndex, SDL_GetError());
modeCount = 0;
}
return (U32)modeCount;
}
const String PlatformWindowManagerSDL::getMonitorMode(U32 monitorIndex, U32 modeIndex)
{
SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
if (SDL_GetDisplayMode(monitorIndex, modeIndex, &mode) != 0)
{
Con::errorf("SDL_GetDisplayMode(%d, %d) failed: %s", monitorIndex, modeIndex, SDL_GetError());
return String::EmptyString;
}
GFXVideoMode vm;
vm.resolution.set(mode.w, mode.h);
vm.refreshRate = mode.refresh_rate;
vm.bitDepth = 32;
vm.antialiasLevel = 0;
vm.fullScreen = false;
vm.wideScreen = false;
return vm.toString();
}
const String PlatformWindowManagerSDL::getMonitorDesktopMode(U32 monitorIndex)
{
SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
if (SDL_GetDesktopDisplayMode(monitorIndex, &mode) != 0)
{
Con::errorf("SDL_GetDesktopDisplayMode(%d) failed: %s", monitorIndex, SDL_GetError());
return String::EmptyString;
}
GFXVideoMode vm;
vm.resolution.set(mode.w, mode.h);
vm.refreshRate = mode.refresh_rate;
int bbp;
unsigned int r, g, b, a;
SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a);
vm.bitDepth = bbp;
vm.antialiasLevel = 0;
vm.fullScreen = false;
vm.wideScreen = ((mode.w / 16) * 9) == mode.h;
return vm.toString();
}
void PlatformWindowManagerSDL::getMonitorRegions(Vector<RectI> &regions)
{
SDL_Rect sdlRect;
@ -251,6 +319,9 @@ PlatformWindow *PlatformWindowManagerSDL::createWindow(GFXDevice *device, const
linkWindow(window);
SDL_SetWindowMinimumSize(window->mWindowHandle, Con::getIntVariable("$Video::minimumXResolution", 1024),
Con::getIntVariable("$Video::minimumYResolution", 720));
return window;
}
@ -513,3 +584,4 @@ AFTER_MODULE_INIT(gfx)
SDL_StopTextInput();
#endif
}

View file

@ -109,6 +109,10 @@ public:
virtual U32 getMonitorCount();
virtual const char* getMonitorName(U32 index);
virtual RectI getMonitorRect(U32 index);
virtual RectI getMonitorUsableRect(U32 index);
virtual U32 getMonitorModeCount(U32 monitorIndex);
virtual const String getMonitorMode(U32 monitorIndex, U32 modeIndex);
virtual const String getMonitorDesktopMode(U32 monitorIndex);
virtual void getMonitorRegions(Vector<RectI> &regions);
virtual PlatformWindow *createWindow(GFXDevice *device, const GFXVideoMode &mode);
@ -133,4 +137,4 @@ public:
void updateSDLTextInputState(KeyboardInputState state);
};
#endif
#endif

View file

@ -54,102 +54,77 @@ $WORD::FULLSCREEN = 2;
$WORD::BITDEPTH = 3;
$WORD::REFRESH = 4;
$WORD::AA = 5;
$Video::ModeTags = "Windowed\tBorderless\tFullscreen";
$Video::ModeWindowed = 0;
$Video::ModeBorderless = 1;
$Video::ModeFullscreen = 2;
$Video::minimumXResolution = 1024;
$Video::minimumYResolution = 720;
function configureCanvas()
{
// Setup a good default if we don't have one already.
if ($pref::Video::Resolution $= "")
$pref::Video::Resolution = "800 600";
if ($pref::Video::FullScreen $= "")
$pref::Video::FullScreen = false;
if ($pref::Video::BitDepth $= "")
$pref::Video::BitDepth = "32";
if ($pref::Video::RefreshRate $= "")
$pref::Video::RefreshRate = "60";
if ($pref::Video::AA $= "")
$pref::Video::AA = "4";
if (($pref::Video::deviceId $= "") || ($pref::Video::deviceId < 0) ||
($pref::Video::deviceId >= Canvas.getMonitorCount()))
$pref::Video::deviceId = 0; // Monitor 0
if (($pref::Video::deviceMode $= "") || ($pref::Video::deviceMode < 0) ||
($pref::Video::deviceMode >= getFieldCount($Video::ModeTags)))
{
$pref::Video::deviceMode = $Video::ModeBorderless;
$pref::Video::mode = Canvas.getBestCanvasRes($pref::Video::deviceId, $pref::Video::deviceMode);
Canvas.modeStrToPrefs($pref::Video::mode);
}
if($cliFullscreen !$= "")
$pref::Video::deviceMode = $cliFullscreen ? 2 : 0;
// Default to borderless at desktop resolution if there is no saved pref or
// command line arg
if (($pref::Video::Resolution $= "") || ($pref::Video::Resolution.x < $Video::minimumXResolution) ||
($pref::Video::Resolution.y < $Video::minimumYResolution))
{
$pref::Video::mode = Canvas.getBestCanvasRes($pref::Video::deviceId, $pref::Video::deviceMode);
Canvas.modeStrToPrefs($pref::Video::mode);
}
if ($pref::Video::deviceMode != $Video::ModeFullscreen)
$pref::Video::FullScreen = false;
%modeStr = Canvas.prefsToModeStr();
echo("--------------");
echo("Attempting to set resolution to \"" @ %modeStr @ "\"");
// Make sure we are running at a valid resolution
if (!Canvas.checkCanvasRes(%modeStr, $pref::Video::deviceId, $pref::Video::deviceMode, true))
{
%modeStr = Canvas.getBestCanvasRes($pref::Video::deviceId, $pref::Video::deviceMode);
Canvas.modeStrToPrefs(%modeStr);
}
%fsLabel = getField($Video::ModeTags, $pref::Video::deviceMode);
%resX = $pref::Video::Resolution.x;
%resY = $pref::Video::Resolution.y;
%fs = $pref::Video::FullScreen;
%bpp = $pref::Video::BitDepth;
%bpp = $pref::Video::BitDepth;
%rate = $pref::Video::RefreshRate;
%aa = $pref::Video::AA;
if($cliFullscreen !$= "") {
%fs = $cliFullscreen;
$cliFullscreen = "";
}
echo("--------------");
echo("Attempting to set resolution to \"" @ %resX SPC %resY SPC %fs SPC %bpp SPC %rate SPC %aa @ "\"");
%deskRes = getDesktopResolution();
%deskResX = getWord(%deskRes, $WORD::RES_X);
%deskResY = getWord(%deskRes, $WORD::RES_Y);
%deskResBPP = getWord(%deskRes, 2);
// We shouldn't be getting this any more but just in case...
if (%bpp $= "Default")
%bpp = %deskResBPP;
// Make sure we are running at a valid resolution
if (%fs $= "0" || %fs $= "false")
{
// Windowed mode has to use the same bit depth as the desktop
%bpp = %deskResBPP;
// Windowed mode also has to run at a smaller resolution than the desktop
if ((%resX >= %deskResX) || (%resY >= %deskResY))
{
warn("Warning: The requested windowed resolution is equal to or larger than the current desktop resolution. Attempting to find a better resolution");
%resCount = Canvas.getModeCount();
for (%i = (%resCount - 1); %i >= 0; %i--)
{
%testRes = Canvas.getMode(%i);
%testResX = getWord(%testRes, $WORD::RES_X);
%testResY = getWord(%testRes, $WORD::RES_Y);
%testBPP = getWord(%testRes, $WORD::BITDEPTH);
if (%testBPP != %bpp)
continue;
if ((%testResX < %deskResX) && (%testResY < %deskResY))
{
// This will work as our new resolution
%resX = %testResX;
%resY = %testResY;
warn("Warning: Switching to \"" @ %resX SPC %resY SPC %bpp @ "\"");
break;
}
}
}
}
$pref::Video::Resolution = %resX SPC %resY;
$pref::Video::FullScreen = %fs;
$pref::Video::BitDepth = %bpp;
$pref::Video::RefreshRate = %rate;
$pref::Video::AA = %aa;
if (%fs == 1 || %fs $= "true")
%fsLabel = "Yes";
else
%fsLabel = "No";
%fsaa = $pref::Video::AA;
%fs = ($pref::Video::deviceMode == 2);
echo("Accepted Mode: " NL
"--Resolution : " @ %resX SPC %resY NL
"--Full Screen : " @ %fsLabel NL
"--Resolution : " @ %resX SPC %resY NL
"--Screen Mode : " @ %fsLabel NL
"--Bits Per Pixel : " @ %bpp NL
"--Refresh Rate : " @ %rate NL
"--AA TypeXLevel : " @ %aa NL
"--Refresh Rate : " @ %rate NL
"--FSAA Level : " @ %fsaa NL
"--------------");
// Actually set the new video mode
Canvas.setVideoMode(%resX, %resY, %fs, %bpp, %rate, %aa);
Canvas.setFocus();
// Lock and unlock the mouse to force the position to sync with the platform window
lockMouse(true);
lockMouse(false);
commandToServer('setClientAspectRatio', %resX, %resY);
@ -157,6 +132,97 @@ function configureCanvas()
// We need to parse the setting between AA modes, and then it's level
// It's formatted as AATypexAALevel
// So, FXAAx4 or MLAAx2
if ( isObject( FXAAPostFX ) )
FXAAPostFX.isEnabled = ( %aa > 0 ) ? true : false;
if ( isObject( FXAA_PostEffect ) )
FXAA_PostEffect.isEnabled = ( %aa > 0 ) ? true : false;
}
function GuiCanvas::modeStrToPrefs(%this, %modeStr)
{
$pref::Video::Resolution = %modeStr.x SPC %modeStr.y;
$pref::Video::FullScreen = getWord(%modeStr, $WORD::FULLSCREEN);
$pref::Video::BitDepth = getWord(%modeStr, $WORD::BITDEPTH);
$pref::Video::RefreshRate = getWord(%modeStr, $WORD::REFRESH);
$pref::Video::AA = getWord(%modeStr, $WORD::AA);
}
function GuiCanvas::prefsToModeStr(%this)
{
%modeStr = $pref::Video::Resolution SPC $pref::Video::FullScreen SPC
$pref::Video::BitDepth SPC $pref::Video::RefreshRate SPC $pref::Video::AA;
return %modeStr;
}
function GuiCanvas::checkCanvasRes(%this, %mode, %deviceId, %deviceMode, %startup)
{
%resX = getWord(%mode, $WORD::RES_X);
%resY = getWord(%mode, $WORD::RES_Y);
// Make sure it meets the minimum resolution requirement
if ((%resX < $Video::minimumXResolution) || (%resY < $Video::minimumYResolution))
return false;
if (%deviceMode == $Video::ModeWindowed)
{ // Windowed must be smaller than the device usable area
%deviceRect = getWords(%this.getMonitorUsableRect(%deviceId), 2);
if ((%resY > %deviceRect.y) || (%resX > (%deviceRect.x - 2)))
return false;
return true;
}
else if (%deviceMode == $Video::ModeBorderless)
{ // Borderless must be at or less than the device res
%deviceRect = getWords(%this.getMonitorRect(%deviceId), 2);
if ((%resX > %deviceRect.x) || (%resY > %deviceRect.y))
return false;
return true;
}
if (!%startup)
return true;
// Checking saved prefs, make sure the mode still exists
%bpp = getWord(%mode, $WORD::BITDEPTH);
%rate = getWord(%mode, $WORD::REFRESH);
%resCount = %this.getMonitorModeCount(%deviceId);
for (%i = (%resCount - 1); %i >= 0; %i--)
{
%testRes = %this.getMonitorMode(%deviceId, %i);
%testResX = getWord(%testRes, $WORD::RES_X);
%testResY = getWord(%testRes, $WORD::RES_Y);
%testBPP = getWord(%testRes, $WORD::BITDEPTH);
%testRate = getWord(%testRes, $WORD::REFRESH);
if ((%testResX == %resX) && (%testResY == %resY) &&
(%testBPP == %bpp) && (%testRate == %rate))
return true;
}
return false;
}
// Find the best video mode setting for the device and display mode
function GuiCanvas::getBestCanvasRes(%this, %deviceId, %deviceMode)
{
if (%deviceMode == $Video::ModeWindowed)
%deviceRect = getWords(%this.getMonitorUsableRect(%deviceId), 2);
else
%deviceRect = getWords(%this.getMonitorRect(%deviceId), 2);
%resCount = %this.getModeCount();
for (%i = %resCount - 1; %i >= 0; %i--)
{
%testRes = %this.getMode(%i);
%resX = getWord(%testRes, $WORD::RES_X);
%resY = getWord(%testRes, $WORD::RES_Y);
if ((%resX > %deviceRect.x) || (%resY > %deviceRect.y))
continue;
return %testRes;
}
// Nothing found? return first mode
return %this.getMonitorMode(%deviceId, 0);
}

View file

@ -721,14 +721,19 @@ function _makePrettyResString( %resString, %giveAspectRation )
return %outRes;
}
function getScreenResolutionList()
function getScreenResolutionList(%deviceID, %deviceMode)
{
%returnsList = "";
%resCount = Canvas.getModeCount();
for (%i = 0; %i < %resCount; %i++)
{
%testResString = Canvas.getMode( %i );
// Make sure it's valid for the monitor and mode selections
if (!Canvas.checkCanvasRes(%testResString, %deviceID, %deviceMode, false))
continue;
%testRes = _makePrettyResString( %testResString );
//sanitize
@ -747,11 +752,40 @@ function getScreenResolutionList()
if(%found)
continue;
if(%i != 0)
if(%returnsList !$= "")
%returnsList = %returnsList @ "\t" @ %testRes;
else
%returnsList = %testRes;
}
return %returnsList;
}
// Return a sorted tab-separated list of all refresh rates available for %resolution.
function getScreenRefreshList(%resolution)
{
%rateArray = new ArrayObject();
%resCount = Canvas.getModeCount();
for (%i = 0; %i < %resCount; %i++)
{
%testRes = Canvas.getMode(%i);
if ((%testRes.x != %resolution.x) || (%testRes.y != %resolution.y))
continue;
%rate = getWord(%testRes, $WORD::REFRESH);
if (%rateArray.getIndexFromKey(%rate) == -1)
%rateArray.add(%rate, %rate);
}
%rateArray.sort(true);
%returnsList = "";
for (%i = 0; %i < %rateArray.count(); %i++)
{
%rate = %rateArray.getKey(%i);
%returnsList = %returnsList @ ((%i == 0) ? %rate : ("\t" @ %rate));
}
if (%returnsList $= "")
%returnsList = "60";
%rateArray.delete();
return %returnsList;
}

View file

@ -27,11 +27,6 @@ $sceneLighting::cacheLighting = 1;
$pref::Video::displayDevice = "D3D11";
$pref::Video::disableVerticalSync = 1;
$pref::Video::Resolution = "1024 768";
$pref::Video::FullScreen = false;
$pref::Video::BitDepth = "32";
$pref::Video::RefreshRate = "60";
$pref::Video::AA = "4";
$pref::Video::defaultFenceCount = 0;
$pref::Video::screenShotSession = 0;
$pref::Video::screenShotFormat = "PNG";

View file

@ -196,13 +196,44 @@ function OptionsMenu::populateDisplaySettingsList(%this)
OptionName.setText("");
OptionDescription.setText("");
%resolutionList = getScreenResolutionList();
OptionsMenuSettingsList.addOptionRow("Display API", "D3D11\tOpenGL", false, "", -1, -30, true, "The display API used for rendering.", $pref::Video::displayDevice);
OptionsMenuSettingsList.addOptionRow("Resolution", %resolutionList, false, "", -1, -30, true, "Resolution of the game window", _makePrettyResString( $pref::Video::mode ));
OptionsMenuSettingsList.addOptionRow("Fullscreen", "No\tYes", false, "", -1, -30, true, "", convertBoolToYesNo($pref::Video::FullScreen));
OptionsMenuSettingsList.addOptionRow("VSync", "No\tYes", false, "", -1, -30, true, "", convertBoolToYesNo(!$pref::Video::disableVerticalSync));
OptionsMenuSettingsList.addOptionRow("Refresh Rate", "30\t60\t75", false, "", -1, -30, true, "", $pref::Video::RefreshRate);
%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", %devicesList, false, "onDisplayModeChange", -1, -30, true, "The display devices the window should be on.", %selectedDevice);
if (%numDevices > 1)
OptionsMenuSettingsList.setRowEnabled(1, true);
else
OptionsMenuSettingsList.setRowEnabled(1, false);
%mode = getField($Video::ModeTags, $pref::Video::deviceMode);
OptionsMenuSettingsList.addOptionRow("Window Mode", $Video::ModeTags, false, "onDisplayModeChange", -1, -30, true, "", %mode);
%resolutionList = getScreenResolutionList($pref::Video::deviceId, $pref::Video::deviceMode);
OptionsMenuSettingsList.addOptionRow("Resolution", %resolutionList, false, "onDisplayResChange", -1, -30, true, "Resolution of the game window", _makePrettyResString( $pref::Video::mode ));
//If they're doing borderless, the window resolution must match the display resolution
if(%mode !$= "Borderless")
OptionsMenuSettingsList.setRowEnabled(3, true);
else
OptionsMenuSettingsList.setRowEnabled(3, false);
OptionsMenuSettingsList.addOptionRow("VSync", "No\tYes", false, "", -1, -30, true, "", convertBoolToYesNo(!$pref::Video::disableVerticalSync));
%refreshList = getScreenRefreshList($pref::Video::mode);
OptionsMenuSettingsList.addOptionRow("Refresh Rate", %refreshList, false, "", -1, -30, true, "", $pref::Video::RefreshRate);
//move to gameplay tab
OptionsMenuSettingsList.addSliderRow("Field of View", 75, 5, "65 100", "", -1, -30);
@ -215,20 +246,8 @@ function OptionsMenu::populateDisplaySettingsList(%this)
function OptionsMenu::applyDisplaySettings(%this)
{
//%newAdapter = GraphicsMenuDriver.getText();
//%numAdapters = GFXInit::getAdapterCount();
%newDevice = OptionsMenuSettingsList.getCurrentOption(0);
/*for( %i = 0; %i < %numAdapters; %i ++ )
{
%targetAdapter = GFXInit::getAdapterName( %i );
if( GFXInit::getAdapterName( %i ) $= %newDevice )
{
%newDevice = GFXInit::getAdapterType( %i );
break;
}
}*/
// Change the device.
if ( %newDevice !$= $pref::Video::displayDevice )
{
@ -324,9 +343,16 @@ function OptionsMenu::applyGraphicsSettings(%this)
$pref::Video::defaultAnisotropy = %level;
}
updateDisplaySettings();
%newFSAA = OptionsMenuSettingsList.getCurrentOption(9);
if (%newFSAA $= "off")
%newFSAA = 0;
if (%newFSAA !$= $pref::Video::AA)
{
$pref::Video::AA = %newFSAA;
configureCanvas();
}
echo("Exporting client prefs");
%prefPath = getPrefpath();
export("$pref::*", %prefPath @ "/clientPrefs.cs", false);
@ -335,37 +361,58 @@ function OptionsMenu::applyGraphicsSettings(%this)
function updateDisplaySettings()
{
//Update the display settings now
$pref::Video::Resolution = getWord(OptionsMenuSettingsList.getCurrentOption(1), 0) SPC getWord(OptionsMenuSettingsList.getCurrentOption(1), 2);
%newBpp = 32; // ... its not 1997 anymore.
$pref::Video::FullScreen = convertOptionToBool(OptionsMenuSettingsList.getCurrentOption(2)) == 0 ? "false" : "true";
$pref::Video::RefreshRate = OptionsMenuSettingsList.getCurrentOption(4);
%newVsync = !convertOptionToBool(OptionsMenuSettingsList.getCurrentOption(3));
//$pref::Video::AA = GraphicsMenuAA.getSelected();
/*if ( %newFullScreen $= "false" )
{
// If we're in windowed mode switch the fullscreen check
// if the resolution is bigger than the desktop.
%deskRes = getDesktopResolution();
%deskResX = getWord(%deskRes, $WORD::RES_X);
%deskResY = getWord(%deskRes, $WORD::RES_Y);
if ( getWord( %newRes, $WORD::RES_X ) > %deskResX ||
getWord( %newRes, $WORD::RES_Y ) > %deskResY )
{
$pref::Video::FullScreen = "true";
GraphicsMenuFullScreen.setStateOn( true );
}
}*/
%deviceName = OptionsMenuSettingsList.getCurrentOption(1);
%newDeviceID = getWord(%deviceName, 0) - 1;
%deviceModeName = OptionsMenuSettingsList.getCurrentOption(2);
%newDeviceMode = 0;
foreach$(%modeName in $Video::ModeTags)
{
if (%deviceModeName $= %modeName)
break;
else
%newDeviceMode++;
}
%newRes = getWord(OptionsMenuSettingsList.getCurrentOption(3), 0) SPC getWord(OptionsMenuSettingsList.getCurrentOption(3), 2);
%newBpp = 32; // ... its not 1997 anymore.
%newFullScreen = %deviceModeName $= "Fullscreen" ? true : false;
%newRefresh = OptionsMenuSettingsList.getCurrentOption(5);
%newVsync = !convertOptionToBool(OptionsMenuSettingsList.getCurrentOption(4));
%newFSAA = $pref::Video::AA;
// Build the final mode string.
%newMode = $pref::Video::Resolution SPC $pref::Video::FullScreen SPC %newBpp SPC $pref::Video::RefreshRate SPC $pref::Video::AA;
%newMode = %newRes SPC %newFullScreen SPC %newBpp SPC %newRefresh SPC %newFSAA;
// Change the video mode.
if ( %newMode !$= $pref::Video::mode ||
%newVsync != $pref::Video::disableVerticalSync )
if ( %newMode !$= $pref::Video::mode || %newDeviceID != $pref::Video::deviceId ||
%newVsync != $pref::Video::disableVerticalSync || %newDeviceMode != $pref::Video::deviceMode)
{
if ( %testNeedApply )
return true;
//****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), %aa);
}
$pref::Video::mode = %newMode;
$pref::Video::disableVerticalSync = %newVsync;
$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();
}
}
@ -537,4 +584,76 @@ function convertBoolToOnOff(%val)
return "On";
else
return "Off";
}
function onDisplayModeChange(%val)
{
// The display device (monitor) or screen mode has changed. Refill the
// resolution list with only available options.
%deviceName = OptionsMenuSettingsList.getCurrentOption(1);
%newDeviceID = getWord(%deviceName, 0) - 1;
%deviceModeName = OptionsMenuSettingsList.getCurrentOption(2);
%newDeviceMode = 0;
foreach$(%modeName in $Video::ModeTags)
{
if (%deviceModeName $= %modeName)
break;
else
%newDeviceMode++;
}
%resolutionList = getScreenResolutionList(%newDeviceID, %newDeviceMode);
// If we're switching to borderless, default to monitor res
if (%newDeviceMode == $Video::ModeBorderless)
%newRes = getWords(Canvas.getMonitorRect(%newDeviceID), 2);
else
{ // Otherwise, if our old resolution is still in the list, attempt to reset it.
%oldRes = getWord(OptionsMenuSettingsList.getCurrentOption(3), 0) SPC getWord(OptionsMenuSettingsList.getCurrentOption(3), 2);
%found = false;
%retCount = getFieldCount(%resolutionList);
for (%i = 0; %i < %retCount; %i++)
{
%existingEntry = getField(%resolutionList, %i);
if ((%existingEntry.x $= %oldRes.x) && (%existingEntry.z $= %oldRes.y))
{
%found = true;
%newRes = %oldRes;
break;
}
}
if (!%found)
{ // Pick the best resoltion available for the device and mode
%newRes = Canvas.getBestCanvasRes(%newDeviceID, %newDeviceMode);
}
}
if(%newDeviceMode == $Video::ModeBorderless)
OptionsMenuSettingsList.setRowEnabled(3, false);
else
OptionsMenuSettingsList.setRowEnabled(3, true);
OptionsMenuSettingsList.setOptions(3, %resolutionList);
OptionsMenuSettingsList.selectOption(3, _makePrettyResString(%newRes));
}
function onDisplayResChange(%val)
{ // The resolution has changed. Setup refresh rates available at this res.
%newRes = getWord(OptionsMenuSettingsList.getCurrentOption(3), 0) SPC getWord(OptionsMenuSettingsList.getCurrentOption(3), 2);
%refreshList = getScreenRefreshList(%newRes);
// If our old rate still exists, select it
%oldRate = OptionsMenuSettingsList.getCurrentOption(5);
%retCount = getFieldCount(%refreshList);
for (%i = 0; %i < %retCount; %i++)
{
%existingEntry = getField(%refreshList, %i);
%newRate = %existingEntry;
if (%existingEntry $= %oldRate)
break;
}
OptionsMenuSettingsList.setOptions(5, %refreshList);
OptionsMenuSettingsList.selectOption(5, %newRate);
}