Re #195 (issues in Display Config menu) : moved the menu code to confscreens and cleaned it up

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@2846 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 28fc8022fa4034b791bfe6020ca13ef1525d4d29
Former-commit-id: eb67811bf5c203fba195b76527a76b7bae5ad96e
This commit is contained in:
pouillot 2010-10-07 21:33:40 +00:00
parent 3ac800f798
commit 272f9b82c3
7 changed files with 576 additions and 335 deletions

View file

@ -22,6 +22,7 @@
#include <tgfclient.h>
#include <displayconfig.h>
#include <graphconfig.h>
#include <openglconfig.h>
#include <soundconfig.h>
@ -44,7 +45,7 @@ OptionOptionInit(void *prevMenu)
CreateStaticControls(param,optionHandle);
CreateButtonControl(optionHandle,param,"display",GfScrMenuInit(optionHandle),GfuiScreenActivate);
CreateButtonControl(optionHandle,param,"display",DisplayMenuInit(optionHandle),GfuiScreenActivate);
CreateButtonControl(optionHandle,param,"graphic",GraphMenuInit(optionHandle),GfuiScreenActivate);
CreateButtonControl(optionHandle,param,"opengl",OpenGLMenuInit(optionHandle),GfuiScreenActivate);
CreateButtonControl(optionHandle,param,"sound",SoundMenuInit(optionHandle),GfuiScreenActivate);

View file

@ -3,11 +3,11 @@ INCLUDE(../../../cmake/macros.cmake)
#PROJECT(confscreens)
SET(CONFSCREENS_HEADERS confscreens.h controlconfig.h playerconfig.h
graphconfig.h joystickconfig.h mouseconfig.h
displayconfig.h graphconfig.h joystickconfig.h mouseconfig.h
openglconfig.h simuconfig.h soundconfig.h aiconfig.h
carsettingsmenu.h hostsettingsmenu.h)
SET(CONFSCREENS_SOURCES controlconfig.cpp playerconfig.cpp graphconfig.cpp
SET(CONFSCREENS_SOURCES controlconfig.cpp playerconfig.cpp displayconfig.cpp graphconfig.cpp
joystickconfig.cpp mouseconfig.cpp openglconfig.cpp
simuconfig.cpp soundconfig.cpp aiconfig.cpp
carsettingsmenu.cpp hostsettingsmenu.cpp

View file

@ -0,0 +1,435 @@
/***************************************************************************
file : displayconfig.cpp
created : October 2010
copyright : (C) 2010 Jean-Philippe Meuret
web : speed-dreams.sourceforge.net
version : $Id$
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/* Display configuration menu */
#include <sstream>
#include <tgfclient.h>
#include "displayconfig.h"
// Some consts.
static const char* ADisplayModes[DisplayMenu::nDisplayModes] = { "Full-screen", "Windowed" };
static const char* AVideoInitModes[DisplayMenu::nVideoInitModes] = { "Compatible", "Best possible" };
// The unique DisplayMenu instance.
static DisplayMenu* PDisplayMenu = 0;
// Call-backs ================================================================
void DisplayMenu::onActivate(void *pDisplayMenu)
{
//GfLogDebug("DisplayMenu::onActivate\n");
// Get the DisplayMenu instance.
DisplayMenu* pMenu = static_cast<DisplayMenu*>(pDisplayMenu);
// Load settings from XML file.
pMenu->loadSettings();
// Initialize GUI from loaded values.
pMenu->updateControls();
}
void DisplayMenu::onChangeColorDepth(tComboBoxInfo *pInfo)
{
// Get the DisplayMenu instance from call-back user data.
DisplayMenu* pMenu = static_cast<DisplayMenu*>(pInfo->userData);
pMenu->setColorDepthIndex(pInfo->nPos);
}
void DisplayMenu::onChangeDisplayMode(tComboBoxInfo *pInfo)
{
// Get the DisplayMenu instance from call-back user data.
DisplayMenu* pMenu = static_cast<DisplayMenu*>(pInfo->userData);
pMenu->setDisplayMode((EDisplayMode)pInfo->nPos);
}
void DisplayMenu::onChangeScreenSize(tComboBoxInfo *pInfo)
{
// Get the DisplayMenu instance from call-back user data.
DisplayMenu* pMenu = static_cast<DisplayMenu*>(pInfo->userData);
pMenu->setScreenSizeIndex(pInfo->nPos);
}
void DisplayMenu::onChangeVideoInitMode(tComboBoxInfo *pInfo)
{
// Get the DisplayMenu instance from call-back user data.
DisplayMenu* pMenu = static_cast<DisplayMenu*>(pInfo->userData);
pMenu->setVideoInitMode((EVideoInitMode)pInfo->nPos);
}
void DisplayMenu::onChangeMaxRefreshRate(void *pDisplayMenu)
{
// Get the DisplayMenu instance from call-back user data.
DisplayMenu* pMenu = static_cast<DisplayMenu*>(pDisplayMenu);
// Get current text from the edit control
const char* pszRefRate =
GfuiEditboxGetString(pMenu->GetMenuHandle(),
pMenu->GetDynamicControlId("MaxRefreshRateEdit"));
// Try and convert it to a valid max refresh rate.
std::istringstream issMaxRefRate(pszRefRate);
int nMaxRefreshRate;
issMaxRefRate >> nMaxRefreshRate;
// If succeeded, save it as the new max refresh rate, otherwise, request for reset.
if (!issMaxRefRate.good())
nMaxRefreshRate = -1;
pMenu->setMaxRefreshRate(nMaxRefreshRate);
}
// Re-init screen to take new graphical settings into account (implies process restart).
void DisplayMenu::onAccept(void *pDisplayMenu)
{
// Get the DisplayMenu instance from call-back user data.
DisplayMenu* pMenu = static_cast<DisplayMenu*>(pDisplayMenu);
// Force current control to loose focus (if one had it) and update associated variable.
GfuiUnSelectCurrent();
// Save display settings.
pMenu->storeSettings();
// Release screen allocated resources.
GfScrShutdown();
// Restart the game.
GfRestart(GfuiMouseIsHWPresent(), GfglIsMultiTexturingEnabled());
// TODO: A nice system to get back to previous display settings if the chosen ones
// keep the game from really restarting (ex: unsupported full screen size) ?
}
void DisplayMenu::onCancel(void *pDisplayMenu)
{
// Get the DisplayMenu instance from call-back user data.
const DisplayMenu* pMenu = static_cast<DisplayMenu*>(pDisplayMenu);
// Back to previous screen.
GfuiScreenActivate(pMenu->GetPreviousMenuHandle());
}
void DisplayMenu::updateControls()
{
int nControlId = GetDynamicControlId("ColorDepthCombo");
int nColorDepthIndex = _nNbColorDepths-1; // Defaults to the max possible supported value.
for (int nColorDepthInd = 0; nColorDepthInd < _nNbColorDepths; nColorDepthInd++)
if (_nColorDepth <= _aColorDepths[nColorDepthInd])
{
nColorDepthIndex = nColorDepthInd;
break;
}
GfuiComboboxSetSelectedIndex(GetMenuHandle(), nControlId, nColorDepthIndex);
nControlId = GetDynamicControlId("DisplayModeCombo");
GfuiComboboxSetSelectedIndex(GetMenuHandle(), nControlId, _eDisplayMode);
resetScreenSizes(_nScreenWidth, _nScreenHeight, _nColorDepth, _eDisplayMode);
nControlId = GetDynamicControlId("VideoInitModeCombo");
GfuiComboboxSetSelectedIndex(GetMenuHandle(), nControlId, _eVideoInitMode);
nControlId = GetDynamicControlId("MaxRefreshRateEdit");
std::ostringstream ossMaxRefRate;
ossMaxRefRate << _nMaxRefreshRate;
GfuiEditboxSetString(GetMenuHandle(), nControlId, ossMaxRefRate.str().c_str());
}
void DisplayMenu::loadSettings()
{
// Load screen config params file.
std::ostringstream ossConfFile;
ossConfFile << GetLocalDir() << GFSCR_CONF_FILE;
void* hScrConfParams =
GfParmReadFile(ossConfFile.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
// Color depth (bits per pixel) (fix the loaded value if not supported).
const int nColorDepth = (int)GfParmGetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_BPP,
NULL, _aColorDepths[_nNbColorDepths-1]);
int nColorDepthIndex = _nNbColorDepths-1; // Defaults to the max possible supported value.
for (int nColorDepthInd = 0; nColorDepthInd < _nNbColorDepths; nColorDepthInd++)
if (nColorDepth <= _aColorDepths[nColorDepthInd]) {
nColorDepthIndex = nColorDepthInd;
break;
}
_nColorDepth = _aColorDepths[nColorDepthIndex];
// Display mode : Full-screen or Windowed.
if (!strcmp("yes", GfParmGetStr(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, "no")))
_eDisplayMode = eFullScreen;
else
_eDisplayMode = eWindowed;
// Screen / window size.
_nScreenWidth = (int)GfParmGetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_X, NULL, 800);
_nScreenHeight = (int)GfParmGetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_Y, NULL, 600);
// Video initialization mode : Compatible or Best.
const char *pszVideoInitMode = GfParmGetStr(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_VINIT,
GFSCR_VAL_VINIT_COMPATIBLE);
_eVideoInitMode =
strcmp(GFSCR_VAL_VINIT_COMPATIBLE, pszVideoInitMode) ? eBestPossible : eCompatible;
// Max. refresh rate (Hz).
_nMaxRefreshRate =
(int)GfParmGetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, NULL, 60);
// Release screen config params file.
GfParmReleaseHandle(hScrConfParams);
}
// Save graphical settings to XML file.
void DisplayMenu::storeSettings() const
{
// Load screen config params file.
std::ostringstream ossConfFile;
ossConfFile << GetLocalDir() << GFSCR_CONF_FILE;
void* hScrConfParams =
GfParmReadFile(ossConfFile.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
// Write new settings.
GfParmSetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_X, (char*)NULL, _nScreenWidth);
GfParmSetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_Y, (char*)NULL, _nScreenHeight);
GfParmSetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_WIN_X, (char*)NULL, _nScreenWidth);
GfParmSetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_WIN_Y, (char*)NULL, _nScreenHeight);
GfParmSetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_BPP, (char*)NULL, _nColorDepth);
GfParmSetNum(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, (char*)NULL, _nMaxRefreshRate);
const char* pszVInitMode =
(_eVideoInitMode == eCompatible) ? GFSCR_VAL_VINIT_COMPATIBLE : GFSCR_VAL_VINIT_BEST;
GfParmSetStr(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, pszVInitMode);
const char* pszDisplMode = (_eDisplayMode == eFullScreen) ? "yes" : "no";
GfParmSetStr(hScrConfParams, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, pszDisplMode);
// Write and release screen config params file.
GfParmWriteFile(NULL, hScrConfParams, "Screen");
GfParmReleaseHandle(hScrConfParams);
}
void DisplayMenu::setDisplayMode(EDisplayMode eMode)
{
_eDisplayMode = eMode;
resetScreenSizes(_nScreenWidth, _nScreenHeight, _nColorDepth, _eDisplayMode);
}
void DisplayMenu::setColorDepthIndex(int nIndex)
{
_nColorDepth = _aColorDepths[nIndex];
resetScreenSizes(_nScreenWidth, _nScreenHeight, _nColorDepth, _eDisplayMode);
}
void DisplayMenu::resetScreenSizes(int nCurrWidth, int nCurrHeight,
int nColorDepth, EDisplayMode eDisplayMode)
{
// Query possible screen sizes for the current display mode and color depth.
int nDefScreenSizes;
tScreenSize* aDefScreenSizes = GfScrGetDefaultSizes(&nDefScreenSizes);
if (_aScreenSizes && _aScreenSizes != aDefScreenSizes)
free(_aScreenSizes);
_aScreenSizes = GfScrGetPossibleSizes(nColorDepth, eDisplayMode == eFullScreen, &_nNbScreenSizes);
// If any size is possible :-) or none :-(, use default hard coded list (temporary).
if (_aScreenSizes == (tScreenSize*)-1 || _aScreenSizes == 0)
{
_aScreenSizes = aDefScreenSizes;
_nNbScreenSizes = nDefScreenSizes;
}
// Update combo-box with new possible sizes.
const int nComboId = GetDynamicControlId("ScreenSizeCombo");
GfuiComboboxClear(GetMenuHandle(), nComboId);
std::ostringstream ossSize;
for (int nSizeIndex = 0; nSizeIndex < _nNbScreenSizes; nSizeIndex++)
{
ossSize.str("");
ossSize << _aScreenSizes[nSizeIndex].width << " x " << _aScreenSizes[nSizeIndex].height;
GfuiComboboxAddText(GetMenuHandle(), nComboId, ossSize.str().c_str());
}
// Try and find the closest screen size to the current choice in the new list.
// 1) Is there an exact match ?
int nScreenSizeIndex = -1;
for (int nSizeInd = 0; nSizeInd < _nNbScreenSizes; nSizeInd++)
if (nCurrWidth == _aScreenSizes[nSizeInd].width
&& nCurrHeight == _aScreenSizes[nSizeInd].height)
{
nScreenSizeIndex = nSizeInd;
break;
}
// 2) Is there an approximative match ?
if (nScreenSizeIndex < 0)
for (int nSizeInd = 0; nSizeInd < _nNbScreenSizes; nSizeInd++)
if (nCurrWidth <= _aScreenSizes[nSizeInd].width
&& nCurrHeight <= _aScreenSizes[nSizeInd].height)
{
nScreenSizeIndex = nSizeInd;
break;
}
// 3) Not found : the closest is the biggest.
if (nScreenSizeIndex < 0)
nScreenSizeIndex = _nNbScreenSizes - 1;
// 4) Store new screen size.
_nScreenWidth = _aScreenSizes[nScreenSizeIndex].width;
_nScreenHeight = _aScreenSizes[nScreenSizeIndex].height;
// Select the found one in the combo-box.
GfuiComboboxSetSelectedIndex(GetMenuHandle(), nComboId, nScreenSizeIndex);
}
void DisplayMenu::setScreenSizeIndex(int nIndex)
{
_nScreenWidth = _aScreenSizes[nIndex].width;
_nScreenHeight = _aScreenSizes[nIndex].height;
}
void DisplayMenu::setVideoInitMode(EVideoInitMode eMode)
{
_eVideoInitMode = eMode;
}
void DisplayMenu::setMaxRefreshRate(int nMaxRefreshRate)
{
// Negative value means : "reset to previous".
if (nMaxRefreshRate > 0)
_nMaxRefreshRate = nMaxRefreshRate;
std::ostringstream ossMaxRefRate;
ossMaxRefRate << _nMaxRefreshRate;
GfuiEditboxSetString(GetMenuHandle(), GetDynamicControlId("MaxRefreshRateEdit"),
ossMaxRefRate.str().c_str());
}
DisplayMenu::DisplayMenu()
: GfuiMenuScreen("displayconfigmenu.xml")
{
_nNbScreenSizes = -1;
_aScreenSizes = 0;
_nNbColorDepths = -1;
_aColorDepths = 0;
_nColorDepth = 24;
_eDisplayMode = eWindowed;
_nScreenWidth = 800;
_nScreenHeight = 600;
_eVideoInitMode = eCompatible;
_nMaxRefreshRate = 60;
}
bool DisplayMenu::initialize(void *pPreviousMenu)
{
// Save the menu to return to.
SetPreviousMenuHandle(pPreviousMenu);
// Create the menu and all its controls.
CreateMenuEx(NULL, this, onActivate, NULL, (tfuiCallback)NULL, 1);
OpenXMLDescriptor();
CreateStaticControls();
CreateComboboxControl("ScreenSizeCombo", this, onChangeScreenSize);
// CreateButtonControl("resleftarrow", this,(void*)-1,onChangeScreenSize);
// CreateButtonControl("resrightarrow", this,(void*)1,onChangeScreenSize);
// ResLabelId = CreateLabelControl("reslabel");
const int nColorDepthComboId =
CreateComboboxControl("ColorDepthCombo", this, onChangeColorDepth);
const int nDisplayModeComboId =
CreateComboboxControl("DisplayModeCombo", this, onChangeDisplayMode);
// Temporary inhibited Max refresh rate parameter.
// TODO. Given that SDL doesn't support vertical refresh rate selection
// (it "automaticaly" takes care of this), the idea I have is to implement
// this as a simple passive wait (with dynamic delay) in ReUpdate.
#if 0
CreateLabelControl("MaxRefreshRateLabel");
CreateEditControl("MaxRefreshRateEdit", this, 0, onChangeMaxRefreshRate);
#endif
const int nVideoInitComboId =
CreateComboboxControl("VideoInitModeCombo", this, onChangeVideoInitMode);
CreateButtonControl("ApplyButton", this, onAccept);
CreateButtonControl("CancelButton", this, onCancel);
AddShortcut(GFUIK_RETURN, "Apply", this, onAccept, 0);
AddShortcut(GFUIK_ESCAPE, "Cancel", this, onCancel, 0);
// TODO Keyboard shortcuts: Add support for shortcuts in GfuiCombobox ?
//AddShortcut(GFUIK_LEFT, "Previous Resolution", this, onChangeScreenSize, 0);
//AddShortcut(GFUIK_RIGHT, "Next Resolution", this, onChangeScreenSize, 0);
AddShortcut(GFUIK_F1, "Help", GetMenuHandle(), GfuiHelpScreen, 0);
AddShortcut(GFUIK_F12, "Screen-Shot", 0, GfuiScreenShot, 0);
CloseXMLDescriptor();
// Load constant value lists in combo-boxes.
// 1) Color depths combo.
_aColorDepths = GfScrGetPossibleColorDepths(&_nNbColorDepths);
std::ostringstream ossColorDepth;
for (int nColorDepthInd = 0; nColorDepthInd < _nNbColorDepths; nColorDepthInd++)
{
ossColorDepth.str("");
ossColorDepth << _aColorDepths[nColorDepthInd];
GfuiComboboxAddText(GetMenuHandle(), nColorDepthComboId, ossColorDepth.str().c_str());
}
// 2) Display modes combo.
for (int nDispModeInd = 0; nDispModeInd < nDisplayModes; nDispModeInd++)
GfuiComboboxAddText(GetMenuHandle(), nDisplayModeComboId, ADisplayModes[nDispModeInd]);
// 3) Video init. modes combo.
for (int nVidInitModeInd = 0; nVidInitModeInd < nVideoInitModes; nVidInitModeInd++)
GfuiComboboxAddText(GetMenuHandle(), nVideoInitComboId, AVideoInitModes[nVidInitModeInd]);
// 4) Screen sizes : not constant, as depends on selected color depth and display mode.
return true;
}
/** Create and activate the display options menu screen.
@ingroup screen
@param precMenu previous menu to return to
*/
void* DisplayMenuInit(void *pPreviousMenu)
{
if (!PDisplayMenu)
PDisplayMenu = new DisplayMenu;
PDisplayMenu->initialize(pPreviousMenu);
return PDisplayMenu->GetMenuHandle();
}

View file

@ -0,0 +1,95 @@
/***************************************************************************
file : displayconfig.h
created : October 2010
copyright : (C) 2010 Jean-Philippe Meuret
web : speed-dreams.sourceforge.net
version : $Id$
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef _DISPLAYCONFIG_H_
#define _DISPLAYCONFIG_H_
#include <tgfclient.h>
#include "confscreens.h"
class DisplayMenu : public GfuiMenuScreen
{
public:
DisplayMenu();
bool initialize(void* pPreviousMenu);
enum EDisplayMode { eFullScreen = 0, eWindowed = 1, nDisplayModes };
enum EVideoInitMode { eCompatible = 0, eBestPossible = 1, nVideoInitModes };
void setDisplayMode(EDisplayMode eMode);
void setColorDepthIndex(int nIndex);
void setScreenSizeIndex(int nIndex);
void setVideoInitMode(EVideoInitMode eMode);
void setMaxRefreshRate(int nMaxRefreshRate);
void storeSettings() const;
void loadSettings();
void updateControls();
protected:
void resetScreenSizes(int nCurrWidth, int nCurrHeight,
int nColorDepth, EDisplayMode eDisplayMode);
// Control callback functions (must be static).
static void onActivate(void *pDisplayMenu);
static void onChangeScreenSize(tComboBoxInfo *pInfo);
static void onChangeColorDepth(tComboBoxInfo *pInfo);
static void onChangeDisplayMode(tComboBoxInfo *pInfo);
static void onChangeVideoInitMode(tComboBoxInfo *pInfo);
static void onChangeMaxRefreshRate(void *pDisplayMenu);
static void onGarage(void *pDisplayMenu);
static void onAccept(void *pDisplayMenu);
static void onCancel(void *pDisplayMenu);
private:
//! Possible screen sizes according to the current color depth and display mode.
int _nNbScreenSizes;
tScreenSize* _aScreenSizes;
//! Possible color depths (bits per pixel).
int _nNbColorDepths;
int* _aColorDepths;
//! Currently selected color depth (inside _aColorDepths).
int _nColorDepth;
//! Currently selected display mode.
EDisplayMode _eDisplayMode;
//! Currently selected screen size.
int _nScreenWidth;
int _nScreenHeight;
//! Currently selected video init. mode.
EVideoInitMode _eVideoInitMode;
//! Currently selected max. refresh rate (Hz).
int _nMaxRefreshRate;
};
CONFSCREENS_API void* DisplayMenuInit(void* pPreviousMenu);
#endif //_DISPLAYCONFIG_H_

View file

@ -306,6 +306,17 @@ GfuiMouseSetHWPresent(void)
GfuiMouseHW = 1;
}
/** Query if the hardware mouse pointer is activated
@ingroup ctrl
@return <tt>0 ... </tt>Ok
<br><tt>-1 .. </tt>Error
*/
bool
GfuiMouseIsHWPresent(void)
{
return GfuiMouseHW != 0;
}
static void
gfuiKeyboardDown(int key, int modifier, int /* x */, int /* y */)
{

View file

@ -23,26 +23,29 @@
@ingroup screen
*/
#include <cstdio>
#include <cstring>
#ifdef WIN32
#include <windows.h>
#ifndef HAVE_CONFIG_H
#define HAVE_CONFIG_H
#endif
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#include <cstdio>
#include <cstring>
#include <cmath>
#ifdef WIN32
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#endif
#include <cmath>
#ifndef WIN32
#include <unistd.h>
#else
#include <process.h>
#endif /* WIN32 */
#include <SDL/SDL.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "version.h"
#endif
#include <portability.h>
#include "tgfclient.h"
@ -50,10 +53,7 @@
#include "glfeatures.h"
#ifdef HAVE_CONFIG_H
#include "version.h"
#endif
// The screen properties.
static int GfScrWidth;
static int GfScrHeight;
static int GfViewWidth;
@ -61,8 +61,8 @@ static int GfViewHeight;
static int GfScrCenX;
static int GfScrCenY;
// The screen surface.
SDL_Surface *ScreenSurface = NULL;
static void *scrHandle = NULL;
/* Default list of screen sizes ("resolutions") in case
something went wrong during hardware / driver capabilities detection */
@ -111,35 +111,17 @@ static tScreenSize ADefScreenSizes[] =
};
static const int NDefScreenSizes = sizeof(ADefScreenSizes) / sizeof(ADefScreenSizes[0]);
static tScreenSize* AScreenSizes = 0;
static int NScreenSizes = 0;
static const char* ADisplayModes[] = { "Full-screen", "Windowed" };
static const int NDisplayModes = sizeof(ADisplayModes) / sizeof(ADisplayModes[0]);
static const char* AVideoInitModes[] = { "Compatible", "Best possible" };
static const int NVideoInitModes = sizeof(AVideoInitModes) / sizeof(AVideoInitModes[0]);
static int* AColorDepths = 0;
static int NColorDepths = 0;
static int NCurScreenSize = 0;
static int NCurDisplayMode = 0;
static int NCurColorDepth = 0;
static int NCurVideoInitMode = 0;
static int NCurMaxFreq = 75;
static int ScreenSizeLabelId;
static int ColorDepthLabelId;
static int DisplayModeLabelId;
static int VideoInitModeLabelId;
#ifdef WIN32
static int MaxFreqEditId;
#endif
static void *paramHdle;
/** Get the default / fallback screen / windows sizes (pixels).
@ingroup screen
@param pnSizes Address of number of default sizes (output).
@return Array of detected possible sizes (static data, never free).
*/
tScreenSize* GfScrGetDefaultSizes(int* pnSizes)
{
*pnSizes = NDefScreenSizes;
return ADefScreenSizes;
}
/** Get the possible screen / windows sizes (pixels) for the given color depth and display mode.
@ingroup screen
@ -147,6 +129,7 @@ static void *paramHdle;
@param bFullScreen Requested display mode : full-screeen mode if true, windowed otherwise.
@param pnSizes Address of number of detected possible sizes (output) (-1 if any size is possible).
@return Array of detected possible sizes (allocated on the heap, must use free at the end), or 0 if no detected possible size, or -1 if any size is possible.
@note The vertical refresh rate is not taken into account as a parameter for detection here, due to SDL API not supporting this ; fortunately, when selecting a given video mode, SDL ensures to (silently) select a safe refresh rate for the selected mode, which may be of some importantce especially in full-screen modes.
*/
tScreenSize* GfScrGetPossibleSizes(int nColorDepth, bool bFullScreen, int* pnSizes)
{
@ -365,11 +348,6 @@ void GfScrInit(int argc, char *argv[])
//GfLogTrace(" Total video memory : %u Kb\n", sdlVideoInfo->video_mem);
GfLogTrace("Maximum pixel depth : %d bits\n", sdlVideoInfo->vfmt->BitsPerPixel);
// Query supported color depths.
if (AColorDepths)
free(AColorDepths);
AColorDepths = GfScrGetPossibleColorDepths(&NColorDepths);
// Get graphical settings from config file.
sprintf(buf, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
handle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
@ -557,17 +535,6 @@ void GfScrInit(int argc, char *argv[])
*/
void GfScrShutdown(void)
{
if (AColorDepths)
{
free(AColorDepths);
AColorDepths = 0;
}
if (AScreenSizes && AScreenSizes != ADefScreenSizes)
{
free(AScreenSizes);
AScreenSizes = 0;
}
}
@ -654,271 +621,3 @@ SDL_Surface* gfScrGetScreenSurface()
{
return ScreenSurface;
}
// Save graphical settings to XML file.
static void
saveParams(void)
{
const int w = AScreenSizes[NCurScreenSize].width;
const int h = AScreenSizes[NCurScreenSize].height;
GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_X, (char*)NULL, w);
GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_Y, (char*)NULL, h);
GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_WIN_X, (char*)NULL, w);
GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_WIN_Y, (char*)NULL, h);
GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_BPP, (char*)NULL, AColorDepths[NCurColorDepth]);
GfParmSetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, (char*)NULL, NCurMaxFreq);
const char* pszVInitMode =
(NCurVideoInitMode == 0) ? GFSCR_VAL_VINIT_COMPATIBLE : GFSCR_VAL_VINIT_BEST;
GfParmSetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, pszVInitMode);
GfParmSetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, NCurDisplayMode == 0 ? "yes" : "no");
GfParmWriteFile(NULL, paramHdle, "Screen");
}
// Re-init screen to take new graphical settings into account (implies process restart).
void
GfScrReinit(void * /* dummy */)
{
// Force current edit to loose focus (if one has it) and update associated variable.
GfuiUnSelectCurrent();
// Save graphical settings.
saveParams();
// Release screen allocated resources.
GfScrShutdown();
// Restart the game.
GfRestart(GfuiMouseHW != 0, GfglIsMultiTexturingEnabled());
}
static void
updateLabelText(void)
{
char buf[32];
sprintf(buf, "%dx%d", AScreenSizes[NCurScreenSize].width, AScreenSizes[NCurScreenSize].height);
GfuiLabelSetText(scrHandle, ScreenSizeLabelId, buf);
sprintf(buf, "%d", AColorDepths[NCurColorDepth]);
GfuiLabelSetText(scrHandle, ColorDepthLabelId, buf);
GfuiLabelSetText(scrHandle, DisplayModeLabelId, ADisplayModes[NCurDisplayMode]);
#ifdef WIN32
sprintf(buf, "%d", NCurMaxFreq);
GfuiEditboxSetString(scrHandle, MaxFreqEditId, buf);
#endif
GfuiLabelSetText(scrHandle, VideoInitModeLabelId, AVideoInitModes[NCurVideoInitMode]);
}
static void
ResPrevNext(void *vdelta)
{
NCurScreenSize = (NCurScreenSize + (int)(long)vdelta + NScreenSizes) % NScreenSizes;
updateLabelText();
}
static void
updateScreenSizes(int nCurrWidth, int nCurrHeight)
{
// Query possible screen sizes for the current display mode and color depth.
if (AScreenSizes && AScreenSizes != ADefScreenSizes)
free(AScreenSizes);
AScreenSizes = GfScrGetPossibleSizes(AColorDepths[NCurColorDepth],
NCurDisplayMode == 0, &NScreenSizes);
// If any size is possible :-) or none :-(, use default hard coded list (temporary).
if (AScreenSizes == (tScreenSize*)-1 || AScreenSizes == 0)
{
AScreenSizes = ADefScreenSizes;
NScreenSizes = NDefScreenSizes;
}
// Try and find the closest screen size to the current choice in the new list.
// 1) Is there an exact match ?
NCurScreenSize = -1;
for (int nSizeInd = 0; nSizeInd < NScreenSizes; nSizeInd++)
{
if (nCurrWidth == AScreenSizes[nSizeInd].width
&& nCurrHeight == AScreenSizes[nSizeInd].height)
{
NCurScreenSize = nSizeInd;
break;
}
}
// 2) Is there an approximative match ?
if (NCurScreenSize < 0)
{
for (int nSizeInd = 0; nSizeInd < NScreenSizes; nSizeInd++)
{
if (nCurrWidth <= AScreenSizes[nSizeInd].width
&& nCurrHeight <= AScreenSizes[nSizeInd].height)
{
NCurScreenSize = nSizeInd;
break;
}
}
}
// 3) Not found : the closest is the biggest.
if (NCurScreenSize < 0)
NCurScreenSize = NScreenSizes - 1;
}
static void
DepthPrevNext(void *vdelta)
{
NCurColorDepth = (NCurColorDepth + (int)(long)vdelta + NColorDepths) % NColorDepths;
updateScreenSizes(AScreenSizes[NCurScreenSize].width, AScreenSizes[NCurScreenSize].height);
updateLabelText();
}
static void
ModePrevNext(void *vdelta)
{
NCurDisplayMode = (NCurDisplayMode + (int)(long)vdelta + NDisplayModes) % NDisplayModes;
updateScreenSizes(AScreenSizes[NCurScreenSize].width, AScreenSizes[NCurScreenSize].height);
updateLabelText();
}
static void
VInitPrevNext(void *vdelta)
{
NCurVideoInitMode = (NCurVideoInitMode + (int)(long)vdelta + NVideoInitModes) % NVideoInitModes;
updateLabelText();
}
static void
loadParams(void)
{
int w, h, bpp;
int i;
// Color depth (bits per pixel).
bpp = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_BPP, NULL, AColorDepths[NColorDepths-1]);
NCurColorDepth = NColorDepths-1; // Defaults to max possible supported value.
for (i = 0; i < NColorDepths; i++) {
if (bpp <= AColorDepths[i]) {
NCurColorDepth = i;
break;
}
}
// Display mode : Full-screen or Windowed.
if (!strcmp("yes", GfParmGetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, "no"))) {
NCurDisplayMode = 0;
} else {
NCurDisplayMode = 1;
}
// Screen / window size.
w = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_X, NULL, 640);
h = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_Y, NULL, 480);
updateScreenSizes(w, h);
// Video initialization mode : Compatible or Best.
NCurVideoInitMode = 0;
const char *tmp = GfParmGetStr(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, GFSCR_VAL_VINIT_COMPATIBLE);
if (strcmp(GFSCR_VAL_VINIT_COMPATIBLE, tmp) == 0) {
NCurVideoInitMode = 0;
} else {
NCurVideoInitMode = 1;
}
// Max. refresh rate (Hz).
NCurMaxFreq = (int)GfParmGetNum(paramHdle, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, NULL, NCurMaxFreq);
}
#ifdef WIN32
static void
ChangeMaxFreq(void * /* dummy */)
{
char buf[32];
char *val;
val = GfuiEditboxGetString(scrHandle, MaxFreqEditId);
NCurMaxFreq = (int)strtol(val, (char **)NULL, 0);
sprintf(buf, "%d", NCurMaxFreq);
GfuiEditboxSetString(scrHandle, MaxFreqEditId, buf);
}
#endif
static void
onActivate(void * /* dummy */)
{
loadParams();
updateLabelText();
}
/** Create and activate the video options menu screen.
@ingroup screen
@param precMenu previous menu to return to
*/
void *
GfScrMenuInit(void *prevMenu)
{
char buf[512];
sprintf(buf, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
paramHdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
if (scrHandle)
return scrHandle;
scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, onActivate, NULL, (tfuiCallback)NULL, 1);
void *param = LoadMenuXML("screenconfigmenu.xml");
CreateStaticControls(param,scrHandle);
CreateButtonControl(scrHandle,param,"resleftarrow",(void*)-1,ResPrevNext);
CreateButtonControl(scrHandle,param,"resrightarrow",(void*)1,ResPrevNext);
ScreenSizeLabelId = CreateLabelControl(scrHandle,param,"reslabel");
CreateButtonControl(scrHandle, param, "accept", NULL, GfScrReinit);
CreateButtonControl(scrHandle, param, "cancel", prevMenu, GfuiScreenActivate);
CreateButtonControl(scrHandle,param,"depthleftarrow",(void*)-1,DepthPrevNext);
CreateButtonControl(scrHandle,param,"depthrightarrow",(void*)1,DepthPrevNext);
ColorDepthLabelId = CreateLabelControl(scrHandle,param,"depthlabel");
CreateButtonControl(scrHandle,param,"displeftarrow",(void*)-1,ModePrevNext);
CreateButtonControl(scrHandle,param,"disprightarrow",(void*)1,ModePrevNext);
DisplayModeLabelId = CreateLabelControl(scrHandle,param,"displabel");
#ifdef WIN32
CreateLabelControl(scrHandle,param,"maxfreqlabel");
MaxFreqEditId = CreateEditControl(scrHandle,param,"freqedit",NULL,NULL,ChangeMaxFreq);
#endif
CreateButtonControl(scrHandle,param,"vmleftarrow",(void*)-1, VInitPrevNext);
CreateButtonControl(scrHandle,param,"vmrightarrow",(void*)1, VInitPrevNext);
VideoInitModeLabelId = CreateLabelControl(scrHandle,param,"vmlabel");
GfParmReleaseHandle(param);
GfuiAddKey(scrHandle, GFUIK_RETURN, "Accept", NULL, GfScrReinit, NULL);
GfuiAddKey(scrHandle, GFUIK_ESCAPE, "Cancel", prevMenu, GfuiScreenActivate, NULL);
GfuiAddKey(scrHandle, GFUIK_LEFT, "Previous Resolution", (void*)-1, ResPrevNext, NULL);
GfuiAddKey(scrHandle, GFUIK_RIGHT, "Next Resolution", (void*)1, ResPrevNext, NULL);
GfuiAddKey(scrHandle, GFUIK_F1, "Help", scrHandle, GfuiHelpScreen, NULL);
GfuiAddKey(scrHandle, GFUIK_F12, "Screen-Shot", NULL, GfuiScreenShot, NULL);
return scrHandle;
}

View file

@ -83,14 +83,13 @@ typedef struct ScreenSize
TGFCLIENT_API void GfScrInit(int argc, char *argv[]);
TGFCLIENT_API void GfScrShutdown(void);
TGFCLIENT_API void *GfScrMenuInit(void *precMenu);
TGFCLIENT_API void GfScrGetSize(int *scrW, int *scrH, int *viewW, int *viewH);
TGFCLIENT_API unsigned char* GfScrCaptureAsImage(int* viewW, int *viewH);
TGFCLIENT_API int GfScrCaptureAsPNG(const char *filename);
TGFCLIENT_API void GfScrReinit(void*);
TGFCLIENT_API int* GfScrGetPossibleColorDepths(int* pnDepths);
TGFCLIENT_API tScreenSize* GfScrGetPossibleSizes(int nColorDepth, bool bFullScreen, int* pnSizes);
TGFCLIENT_API tScreenSize* GfScrGetDefaultSizes(int* pnSizes);
/*****************************
* GUI interface (low-level) *
@ -311,6 +310,7 @@ TGFCLIENT_API void GfuiMouseHide(void);
TGFCLIENT_API void GfuiMouseShow(void);
TGFCLIENT_API void GfuiMouseToggleVisibility(void);
TGFCLIENT_API void GfuiMouseSetHWPresent(void);
TGFCLIENT_API bool GfuiMouseIsHWPresent(void);
/* All widgets */