summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-07-29 15:09:53 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-07-29 15:09:53 +0200
commit7c5a3514dd6e907866bddcbb09b4d9cbd958dd8e (patch)
tree00aaece75d43bd35a3997bf4eacdfd103d29d5c7
parent72c0188ec37c3783133baf6960d72cb3c9d12a6c (diff)
downloadcolobot-7c5a3514dd6e907866bddcbb09b4d9cbd958dd8e.tar.gz
colobot-7c5a3514dd6e907866bddcbb09b4d9cbd958dd8e.tar.bz2
colobot-7c5a3514dd6e907866bddcbb09b4d9cbd958dd8e.zip
Video mode changing
- added video mode querying & changing - added joystick querying & changing - cleaned up CApplication interface
-rw-r--r--src/app/app.cpp408
-rw-r--r--src/app/app.h123
-rw-r--r--src/common/event.h33
-rw-r--r--src/graphics/core/device.h10
-rw-r--r--src/graphics/core/texture.h10
-rw-r--r--src/graphics/engine/engine.cpp20
-rw-r--r--src/graphics/engine/engine.h21
-rw-r--r--src/graphics/opengl/gldevice.cpp44
-rw-r--r--src/graphics/opengl/gldevice.h6
-rw-r--r--src/math/intsize.h61
-rw-r--r--src/math/size.h66
11 files changed, 580 insertions, 222 deletions
diff --git a/src/app/app.cpp b/src/app/app.cpp
index c778a63..5c6ef49 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -56,19 +56,14 @@ struct ApplicationPrivate
SDL_Event currentEvent;
//! Joystick
SDL_Joystick *joystick;
- //! Index of joystick device
- int joystickIndex;
//! Id of joystick timer
SDL_TimerID joystickTimer;
- //! Current configuration of OpenGL display device
- Gfx::GLDeviceConfig deviceConfig;
ApplicationPrivate()
{
memset(&currentEvent, 0, sizeof(SDL_Event));
surface = NULL;
joystick = NULL;
- joystickIndex = 0;
joystickTimer = 0;
}
};
@@ -77,11 +72,8 @@ struct ApplicationPrivate
CApplication::CApplication()
{
- m_private = new ApplicationPrivate();
- m_exitCode = 0;
-
- m_iMan = new CInstanceManager();
-
+ m_private = new ApplicationPrivate();
+ m_iMan = new CInstanceManager();
m_eventQueue = new CEventQueue(m_iMan);
m_engine = NULL;
@@ -90,21 +82,16 @@ CApplication::CApplication()
m_sound = NULL;
m_keyState = 0;
- m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
-
- m_active = false;
- m_activateApp = false;
- m_ready = false;
- m_joystickEnabled = false;
+ m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
- m_time = 0.0f;
+ m_exitCode = 0;
+ m_active = false;
+ m_debugMode = false;
- m_windowTitle = "COLOBOT";
+ m_windowTitle = "COLOBOT";
- m_showStats = false;
- m_debugMode = false;
- m_setupMode = true;
+ m_joystickEnabled = false;
m_dataPath = "./data";
@@ -139,7 +126,6 @@ bool CApplication::ParseArguments(int argc, char *argv[])
if (arg == "-debug")
{
- m_showStats = true;
SetDebugMode(true);
}
else if (arg == "-datadir")
@@ -165,7 +151,7 @@ bool CApplication::Create()
// TODO: verify that data directory exists
// Temporarily -- only in windowed mode
- m_private->deviceConfig.fullScreen = false;
+ m_deviceConfig.fullScreen = false;
// Create the 3D engine
m_engine = new Gfx::CEngine(m_iMan, this);
@@ -186,71 +172,30 @@ bool CApplication::Create()
if (SDL_Init(initFlags) < 0)
{
- SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL initialization error:\n" +
- std::string(SDL_GetError()) );
+ SystemDialog( SDT_ERROR, "COLOBOT - Fatal Error",
+ "SDL initialization error:\n" +
+ std::string(SDL_GetError()) );
m_exitCode = 2;
return false;
}
if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0)
{
- SystemDialog( SDT_ERROR, "COLOBOT - Error", std::string("SDL_Image initialization error:\n") +
- std::string(IMG_GetError()) );
+ SystemDialog( SDT_ERROR, "COLOBOT - Fatal Error",
+ std::string("SDL_Image initialization error:\n") +
+ std::string(IMG_GetError()) );
m_exitCode = 3;
return false;
}
- const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
- if (videoInfo == NULL)
- {
- SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL error while getting video info:\n " +
- std::string(SDL_GetError()) );
- m_exitCode = 2;
- return false;
- }
-
- Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
-
- if (m_private->deviceConfig.resizeable)
- videoFlags |= SDL_RESIZABLE;
-
- // Use hardware surface if available
- if (videoInfo->hw_available)
- videoFlags |= SDL_HWSURFACE;
- else
- videoFlags |= SDL_SWSURFACE;
-
- // Enable hardware blit if available
- if (videoInfo->blit_hw)
- videoFlags |= SDL_HWACCEL;
-
- if (m_private->deviceConfig.fullScreen)
- videoFlags |= SDL_FULLSCREEN;
-
- // Set OpenGL attributes
-
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, m_private->deviceConfig.redSize);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, m_private->deviceConfig.greenSize);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, m_private->deviceConfig.blueSize);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, m_private->deviceConfig.alphaSize);
-
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, m_private->deviceConfig.depthSize);
-
- if (m_private->deviceConfig.doubleBuf)
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-
- /* If hardware acceleration specifically requested, this will force the hw accel
- and fail with error if not available */
- if (m_private->deviceConfig.hardwareAccel)
- SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
-
- m_private->surface = SDL_SetVideoMode(m_private->deviceConfig.width, m_private->deviceConfig.height,
- m_private->deviceConfig.bpp, videoFlags);
+ if (! CreateVideoSurface())
+ return false; // dialog is in function
if (m_private->surface == NULL)
{
- SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("SDL error while setting video mode:\n") +
- std::string(SDL_GetError()) );
+ SystemDialog( SDT_ERROR, "COLOBT - Fatal Error",
+ std::string("SDL error while setting video mode:\n") +
+ std::string(SDL_GetError()) );
m_exitCode = 2;
return false;
}
@@ -269,11 +214,12 @@ bool CApplication::Create()
// The video is ready, we can create and initalize the graphics device
- m_device = new Gfx::CGLDevice();
+ m_device = new Gfx::CGLDevice(m_deviceConfig);
if (! m_device->Create() )
{
- SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("Error in CDevice::Create() :\n") +
- std::string(m_device->GetError()) );
+ SystemDialog( SDT_ERROR, "COLOBT - Fatal Error",
+ std::string("Error in CDevice::Create() :\n") +
+ std::string(m_device->GetError()) );
m_exitCode = 1;
return false;
}
@@ -281,23 +227,74 @@ bool CApplication::Create()
m_engine->SetDevice(m_device);
if (! m_engine->Create() )
{
- SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("Error in CEngine::Create() :\n") +
- std::string(m_engine->GetError()) );
+ SystemDialog( SDT_ERROR, "COLOBT - Fatal Error",
+ std::string("Error in CEngine::Create() :\n") +
+ std::string(m_engine->GetError()) );
m_exitCode = 1;
return false;
}
if (! m_engine->AfterDeviceSetInit() )
{
- SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("Error in CEngine::AfterDeviceSetInit() :\n") +
- std::string(m_engine->GetError()) );
+ SystemDialog( SDT_ERROR, "COLOBT - Fatal Error",
+ std::string("Error in CEngine::AfterDeviceSetInit() :\n") +
+ std::string(m_engine->GetError()) );
m_exitCode = 1;
return false;
}
+ return true;
+}
+
+bool CApplication::CreateVideoSurface()
+{
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+ if (videoInfo == NULL)
+ {
+ SystemDialog( SDT_ERROR, "COLOBOT - Fatal Error",
+ std::string("SDL error while getting video info:\n ") +
+ std::string(SDL_GetError()) );
+ m_exitCode = 2;
+ return false;
+ }
+
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+ // Use hardware surface if available
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
+
+ // Enable hardware blit if available
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
+
+ if (m_deviceConfig.fullScreen)
+ videoFlags |= SDL_FULLSCREEN;
+
+ if (m_deviceConfig.resizeable)
+ videoFlags |= SDL_RESIZABLE;
+
+ // Set OpenGL attributes
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, m_deviceConfig.redSize);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, m_deviceConfig.greenSize);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, m_deviceConfig.blueSize);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, m_deviceConfig.alphaSize);
+
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, m_deviceConfig.depthSize);
+
+ if (m_deviceConfig.doubleBuf)
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ /* If hardware acceleration specifically requested, this will force the hw accel
+ and fail with error if not available */
+ if (m_deviceConfig.hardwareAccel)
+ SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
- // The app is ready to go
- m_ready = true;
+ m_private->surface = SDL_SetVideoMode(m_deviceConfig.size.w, m_deviceConfig.size.h,
+ m_deviceConfig.bpp, videoFlags);
return true;
}
@@ -351,15 +348,73 @@ void CApplication::Destroy()
SDL_Quit();
}
+bool CApplication::ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig)
+{
+ static bool restore = false;
+
+ m_lastDeviceConfig = m_deviceConfig;
+ m_deviceConfig = newConfig;
+
+
+ SDL_FreeSurface(m_private->surface);
+
+ if (! CreateVideoSurface())
+ {
+ // Fatal error, so post the quit event
+ m_eventQueue->AddEvent(Event(EVENT_QUIT));
+ return false;
+ }
+
+ if (m_private->surface == NULL)
+ {
+ if (! restore)
+ {
+ SystemDialog( SDT_ERROR, "COLOBT - Error",
+ std::string("SDL error while setting video mode:\n") +
+ std::string(SDL_GetError()) + std::string("\n") +
+ std::string("Previous mode will be restored") );
+
+ restore = true;
+ ChangeVideoConfig(m_lastDeviceConfig);
+ return false;
+ }
+ else
+ {
+ restore = false;
+
+ SystemDialog( SDT_ERROR, "COLOBT - Fatal Error",
+ std::string("SDL error while restoring previous video mode:\n") +
+ std::string(SDL_GetError()) );
+
+
+ // Fatal error, so post the quit event
+ m_eventQueue->AddEvent(Event(EVENT_QUIT));
+ return false;
+ }
+ }
+
+ ( static_cast<Gfx::CGLDevice*>(m_device) )->ConfigChanged(m_deviceConfig);
+
+ m_engine->ResetAfterDeviceChanged();
+
+ return true;
+}
+
bool CApplication::OpenJoystick()
{
- m_private->joystick = SDL_JoystickOpen(m_private->joystickIndex);
+ if ( (m_joystick.index < 0) || (m_joystick.index >= SDL_NumJoysticks()) )
+ return false;
+
+ m_private->joystick = SDL_JoystickOpen(m_joystick.index);
if (m_private->joystick == NULL)
return false;
+ m_joystick.axisCount = SDL_JoystickNumAxes(m_private->joystick);
+ m_joystick.buttonCount = SDL_JoystickNumButtons(m_private->joystick);
+
// Create the vectors with joystick axis & button states to exactly the required size
- m_joyAxeState = std::vector<int>(SDL_JoystickNumAxes(m_private->joystick), 0);
- m_joyButtonState = std::vector<bool>(SDL_JoystickNumButtons(m_private->joystick), false);
+ m_joyAxeState = std::vector<int>(m_joystick.axisCount, 0);
+ m_joyButtonState = std::vector<bool>(m_joystick.buttonCount, false);
// Create a timer for polling joystick state
m_private->joystickTimer = SDL_AddTimer(JOYSTICK_TIMER_INTERVAL, JoystickTimerCallback, NULL);
@@ -367,7 +422,6 @@ bool CApplication::OpenJoystick()
return true;
}
-
void CApplication::CloseJoystick()
{
// Timer will remove itself automatically
@@ -376,6 +430,17 @@ void CApplication::CloseJoystick()
m_private->joystick = NULL;
}
+bool CApplication::ChangeJoystick(const JoystickDevice &newJoystick)
+{
+ if ( (newJoystick.index < 0) || (newJoystick.index >= SDL_NumJoysticks()) )
+ return false;
+
+ if (m_private->joystick != NULL)
+ CloseJoystick();
+
+ return OpenJoystick();
+}
+
Uint32 JoystickTimerCallback(Uint32 interval, void *)
{
CApplication *app = CApplication::GetInstancePointer();
@@ -452,6 +517,8 @@ int CApplication::Run()
// To be sure no old event remains
m_private->currentEvent.type = SDL_NOEVENT;
+ // Call SDL_PumpEvents() only once here
+ // (SDL_PeepEvents() doesn't call it)
if (m_active)
SDL_PumpEvents();
@@ -462,11 +529,11 @@ int CApplication::Run()
int count = 0;
// Use SDL_PeepEvents() if the app is active, so we can use idle time to
- // render the scene. Else, use SDL_PollEvent() to avoid eating CPU time.
+ // render the scene. Else, use SDL_WaitEvent() to avoid eating CPU time.
if (m_active)
count = SDL_PeepEvents(&m_private->currentEvent, 1, SDL_GETEVENT, SDL_ALLEVENTS);
else
- count = SDL_PollEvent(&m_private->currentEvent);
+ count = SDL_WaitEvent(&m_private->currentEvent);
// If received an event
if (count > 0)
@@ -492,7 +559,7 @@ int CApplication::Run()
}
// Enter game update & frame rendering only if active
- if (m_active && m_ready)
+ if (m_active)
{
Event event;
while (m_eventQueue->GetEvent(event))
@@ -554,14 +621,14 @@ PressState TranslatePressState(unsigned char state)
- y: 0=down, 1=up */
Math::Point CApplication::WindowToInterfaceCoords(Math::IntPoint pos)
{
- return Math::Point( (float)pos.x / (float)m_private->deviceConfig.width,
- 1.0f - (float)pos.y / (float)m_private->deviceConfig.height);
+ return Math::Point( (float)pos.x / (float)m_deviceConfig.size.w,
+ 1.0f - (float)pos.y / (float)m_deviceConfig.size.h);
}
Math::IntPoint CApplication::InterfaceToWindowCoords(Math::Point pos)
{
- return Math::IntPoint((int)(pos.x * m_private->deviceConfig.width),
- (int)((1.0f - pos.y) * m_private->deviceConfig.height));
+ return Math::IntPoint((int)(pos.x * m_deviceConfig.size.w),
+ (int)((1.0f - pos.y) * m_deviceConfig.size.h));
}
/** The SDL event parsed is stored internally.
@@ -626,6 +693,19 @@ Event CApplication::ParseEvent()
event.joyButton.button = m_private->currentEvent.jbutton.button;
event.joyButton.state = TranslatePressState(m_private->currentEvent.jbutton.state);
}
+ else if (m_private->currentEvent.type == SDL_ACTIVEEVENT)
+ {
+ event.type = EVENT_ACTIVE;
+
+ if (m_private->currentEvent.active.type & SDL_APPINPUTFOCUS)
+ event.active.flags |= ACTIVE_INPUT;
+ if (m_private->currentEvent.active.type & SDL_APPMOUSEFOCUS)
+ event.active.flags |= ACTIVE_MOUSE;
+ if (m_private->currentEvent.active.type & SDL_APPACTIVE)
+ event.active.flags |= ACTIVE_APP;
+
+ event.active.gain = m_private->currentEvent.active.gain == 1;
+ }
return event;
}
@@ -636,6 +716,14 @@ Event CApplication::ParseEvent()
bool CApplication::ProcessEvent(const Event &event)
{
CLogger *l = GetLogger();
+
+ if (event.type == EVENT_ACTIVE)
+ {
+ m_active = event.active.gain;
+ if (m_debugMode)
+ l->Info("Focus change: active = %s\n", m_active ? "true" : "false");
+ }
+
// Print the events in debug mode to test the code
if (m_debugMode)
{
@@ -672,6 +760,11 @@ bool CApplication::ProcessEvent(const Event &event)
l->Info(" button = %d\n", event.joyButton.button);
l->Info(" state = %s\n", (event.joyButton.state == STATE_PRESSED) ? "STATE_PRESSED" : "STATE_RELEASED");
break;
+ case EVENT_ACTIVE:
+ l->Info("EVENT_ACTIVE:\n");
+ l->Info(" flags = 0x%x\n", event.active.flags);
+ l->Info(" gain = %s\n", event.active.gain ? "true" : "false");
+ break;
default:
break;
}
@@ -688,48 +781,58 @@ bool CApplication::Render()
if (! result)
return false;
- if (m_private->deviceConfig.doubleBuf)
+ if (m_deviceConfig.doubleBuf)
SDL_GL_SwapBuffers();
return true;
}
-/** Called in to toggle the pause state of the app. */
-void CApplication::Pause(bool pause)
-{
- static long appPausedCount = 0L;
-
- appPausedCount += ( pause ? +1 : -1 );
- m_ready = appPausedCount == 0;
-
- // Handle the first pause request (of many, nestable pause requests)
- if( pause && ( 1 == appPausedCount ) )
- {
- // Stop the scene from animating
- //m_engine->TimeEnterGel();
- }
-
- // Final pause request done
- if (appPausedCount == 0)
- {
- // Restart the scene
- //m_engine->TimeExitGel();
- }
-}
-
void CApplication::StepSimulation(float rTime)
{
// TODO
}
-void CApplication::SetShowStat(bool show)
+VideoQueryResult CApplication::GetVideoResolutionList(std::vector<Math::IntSize> &resolutions,
+ bool fullScreen, bool resizeable)
{
- m_showStats = show;
-}
+ resolutions.clear();
-bool CApplication::GetShowStat()
-{
- return m_showStats;
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+ if (videoInfo == NULL)
+ return VIDEO_QUERY_ERROR;
+
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+ // Use hardware surface if available
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
+
+ // Enable hardware blit if available
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
+
+ if (resizeable)
+ videoFlags |= SDL_RESIZABLE;
+
+ if (fullScreen)
+ videoFlags |= SDL_FULLSCREEN;
+
+
+ SDL_Rect **modes = SDL_ListModes(NULL, videoFlags);
+
+ if (modes == (SDL_Rect **)0)
+ return VIDEO_QUERY_NONE; // no modes available
+
+ if (modes == (SDL_Rect **)-1)
+ return VIDEO_QUERY_ALL; // all resolutions are possible
+
+
+ for (int i = 0; modes[i] != NULL; ++i)
+ resolutions.push_back(Math::IntSize(modes[i]->w, modes[i]->h));
+
+ return VIDEO_QUERY_OK;
}
void CApplication::SetDebugMode(bool mode)
@@ -742,11 +845,6 @@ bool CApplication::GetDebugMode()
return m_debugMode;
}
-bool CApplication::GetSetupMode()
-{
- return m_setupMode;
-}
-
void CApplication::FlushPressKey()
{
// TODO
@@ -803,6 +901,28 @@ Math::Point CApplication::GetSystemMousePos()
return m_systemMousePos;
}
+std::vector<JoystickDevice> CApplication::GetJoystickList()
+{
+ std::vector<JoystickDevice> result;
+
+ int count = SDL_NumJoysticks();
+
+ for (int index = 0; index < count; ++index)
+ {
+ JoystickDevice device;
+ device.index = index;
+ device.name = SDL_JoystickName(index);
+ result.push_back(device);
+ }
+
+ return result;
+}
+
+JoystickDevice CApplication::GetJoystick()
+{
+ return m_joystick;
+}
+
void CApplication::SetJoystickEnabled(bool enable)
{
m_joystickEnabled = enable;
@@ -825,32 +945,6 @@ bool CApplication::GetJoystickEnabled()
return m_joystickEnabled;
}
-bool CApplication::WriteScreenShot(char *filename, int width, int height)
-{
- // TODO
- return false;
-}
-
-void CApplication::InitText()
-{
- // TODO
-}
-
-void CApplication::DrawSuppl()
-{
- // TODO
-}
-
-void CApplication::ShowStats()
-{
- // TODO
-}
-
-void CApplication::OutputText(long x, long y, char* str)
-{
- // TODO
-}
-
std::string CApplication::GetDataFilePath(const std::string& dirName, const std::string& fileName)
{
return m_dataPath + "/" + dirName + "/" + fileName;
diff --git a/src/app/app.h b/src/app/app.h
index 956eab8..483aa55 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -24,6 +24,8 @@
#include "common/singleton.h"
#include "graphics/core/device.h"
#include "graphics/engine/engine.h"
+#include "graphics/opengl/gldevice.h"
+#include "math/intsize.h"
#include <string>
#include <vector>
@@ -34,6 +36,35 @@ class CEvent;
class CRobotMain;
class CSound;
+/**
+ \struct JoystickDevice
+ \brief Information about a joystick device */
+struct JoystickDevice
+{
+ //! Device index (-1 = invalid device)
+ int index;
+ //! Device name
+ std::string name;
+ //! Number of axes (only available after joystick opened)
+ int axisCount;
+ //! Number of buttons (only available after joystick opened)
+ int buttonCount;
+
+ JoystickDevice()
+ : index(-1), axisCount(0), buttonCount(0) {}
+};
+
+/**
+ \enum VideoQueryResult
+ \brief Result of querying for available video resolutions */
+enum VideoQueryResult
+{
+ VIDEO_QUERY_ERROR,
+ VIDEO_QUERY_NONE,
+ VIDEO_QUERY_ALL,
+ VIDEO_QUERY_OK
+};
+
struct ApplicationPrivate;
@@ -46,26 +77,38 @@ struct ApplicationPrivate;
*
* It is a singleton class with only one instance that can be created.
*
- * Creation of other main objects
+ * \section Creation Creation of other main objects
*
* The class creates the only instance of CInstanceManager, CEventQueue, CEngine,
* CRobotMain and CSound classes.
*
- * Window management
+ * \section Window Window management
*
* The class is responsible for creating app window, setting and changing the video mode,
- * setting the position of mouse and changing the cursor, grabbing and writing screenshots.
+ * joystick management, grabbing input and changing the system mouse cursor
+ * position and visibility.
+ * ("System mouse cursor" means the cursor displayed by the OS in constrast to the cursor
+ * displayed by CEngine).
+ *
+ * \section Events Events
*
- * Events
+ * Events are taken from SDL event queue, translated to common events from src/common.h
+ * and pushed to global event queue CEventQueue.
*
- * Events are taken from SDL event queue and either handled by CApplication or translated
- * to common events from src/common.h and pushed to global event queue CEventQueue.
* Joystick events are generated somewhat differently, by running a separate timer,
* polling the device for changes and synthesising events on change. It avoids flooding
* the event queue with too many joystick events and the granularity of the timer can be
* adjusted.
*
- * The events are further handled in CRobotMain class.
+ * The events are passed to ProcessEvent() of classes in this order: CApplication, CEngine
+ * and CRobotMain. CApplication and CEngine's ProcessEvent() functions return bool, which
+ * means whether to pass the event on, or stop the chain. This is to enable handling some
+ * events which are internal to CApplication or CEngine.
+ *
+ * \section Portability Portability
+ *
+ * Currently, the class only handles OpenGL devices. SDL can be used with DirectX, but
+ * for that to work, video initialization and video setting must be done differently.
*
*/
class CApplication : public CSingleton<CApplication>
@@ -89,26 +132,36 @@ public:
//! Cleans up before exit
void Destroy();
- //! Enters the pause mode
- void Pause(bool pause);
+ //! Returns a list of possible video modes
+ VideoQueryResult GetVideoResolutionList(std::vector<Math::IntSize> &resolutions,
+ bool fullScreen, bool resizeable);
+
+ //! Returns the current video mode
+ Gfx::GLDeviceConfig GetVideoConfig();
+
+ //! Change the video mode to given mode
+ bool ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig);
//! Updates the simulation state
void StepSimulation(float rTime);
- //! Polls the state of joystick axes and buttons
- void UpdateJoystick();
-
- void SetShowStat(bool show);
- bool GetShowStat();
+ //! Returns a list of available joystick devices
+ std::vector<JoystickDevice> GetJoystickList();
- void SetDebugMode(bool mode);
- bool GetDebugMode();
+ //! Returns info about the current joystick
+ JoystickDevice GetJoystick();
- bool GetSetupMode();
+ //! Change the current joystick device
+ bool ChangeJoystick(const JoystickDevice &newJoystick);
+ //! Enables/disables joystick
void SetJoystickEnabled(bool enable);
+ //! Returns whether joystick is enabled
bool GetJoystickEnabled();
+ //! Polls the state of joystick axes and buttons
+ void UpdateJoystick();
+
void FlushPressKey();
void ResetKey();
void SetKey(int keyRank, int option, int key);
@@ -129,12 +182,18 @@ public:
//! Returns the position of system mouse cursor (in interface coords)
Math::Point GetSystemMousePos();
- bool WriteScreenShot(char *filename, int width, int height);
+ //! Enables/disables debug mode (prints more info in logger)
+ void SetDebugMode(bool mode);
+ //! Returns whether debug mode is enabled
+ bool GetDebugMode();
//! Returns the full path to a file in data directory
std::string GetDataFilePath(const std::string &dirName, const std::string &fileName);
protected:
+ //! Creates the window's SDL_Surface
+ bool CreateVideoSurface();
+
//! Processes the captured SDL event to Event struct
Event ParseEvent();
//! Handles some incoming events
@@ -152,11 +211,6 @@ protected:
//! Converts the interface coords to window coords
Math::IntPoint InterfaceToWindowCoords(Math::Point pos);
- void InitText();
- void DrawSuppl();
- void ShowStats();
- void OutputText(long x, long y, char* str);
-
protected:
//! Instance manager
CInstanceManager* m_iMan;
@@ -175,17 +229,15 @@ protected:
//! Code to return at exit
int m_exitCode;
-
+ //! Whether application window is active
bool m_active;
- bool m_activateApp;
- bool m_ready;
-
- bool m_showStats;
+ //! Whether debug mode is enabled
bool m_debugMode;
- bool m_setupMode;
- //! Whether joystick is enabled
- bool m_joystickEnabled;
+ //! Current configuration of OpenGL display device
+ Gfx::GLDeviceConfig m_deviceConfig;
+ //! Previous configuration of OpenGL display device
+ Gfx::GLDeviceConfig m_lastDeviceConfig;
//! Text set as window title
std::string m_windowTitle;
@@ -196,14 +248,17 @@ protected:
Math::Point m_systemMousePos;
long m_mouseWheel;
+ long m_key[50][2];
+
+ //! Info about current joystick device
+ JoystickDevice m_joystick;
+ //! Whether joystick is enabled
+ bool m_joystickEnabled;
//! Current state of joystick axes; may be updated from another thread
std::vector<int> m_joyAxeState;
//! Current state of joystick buttons; may be updated from another thread
std::vector<bool> m_joyButtonState;
- float m_time;
- long m_key[50][2];
-
//! Path to directory with data files
std::string m_dataPath;
};
diff --git a/src/common/event.h b/src/common/event.h
index 6ce1a79..0d9aa7c 100644
--- a/src/common/event.h
+++ b/src/common/event.h
@@ -55,6 +55,9 @@ enum EventType
//! Event sent after releasing a key
EVENT_KEY_UP = 9,
+ //! Event sent when application window loses/gains focus
+ EVENT_ACTIVE = 10,
+
//? EVENT_CHAR = 10,
//? EVENT_FOCUS = 11,
@@ -608,7 +611,7 @@ struct JoyAxisEventData
};
/** \struct JoyButtonEventData
- \brief Joystick button event structure */
+ \brief Additional data for joystick button event */
struct JoyButtonEventData
{
//! The joystick button index
@@ -620,7 +623,31 @@ struct JoyButtonEventData
: button(0), state(STATE_PRESSED) {}
};
-// TODO: JoyHatEventData? JoyBallEventData?
+/** \enum ActiveEventFlags
+ \brief Type of focus gained/lost */
+enum ActiveEventFlags
+{
+ //! Application window focus
+ ACTIVE_APP = 0x01,
+ //! Input focus
+ ACTIVE_INPUT = 0x02,
+ //! Mouse focus
+ ACTIVE_MOUSE = 0x04
+
+};
+
+/** \struct ActiveEventData
+ \brief Additional data for active event */
+struct ActiveEventData
+{
+ //! Flags (bitmask of enum values ActiveEventFlags)
+ unsigned char flags = 0;
+ //! True if the focus was gained; false otherwise
+ bool gain;
+
+ ActiveEventData()
+ : flags(0), gain(false) {}
+};
/**
@@ -652,6 +679,8 @@ struct Event
JoyAxisEventData joyAxis;
//! Additional data for EVENT_JOY_AXIS
JoyButtonEventData joyButton;
+ //! Additional data for EVENT_ACTIVE
+ ActiveEventData active;
//? long param; // parameter
//? Math::Point pos; // mouse position (0 .. 1)
diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h
index ae612b7..1f6cacf 100644
--- a/src/graphics/core/device.h
+++ b/src/graphics/core/device.h
@@ -25,6 +25,7 @@
#include "graphics/core/material.h"
#include "graphics/core/texture.h"
#include "graphics/core/vertex.h"
+#include "math/intsize.h"
#include "math/matrix.h"
#include <string>
@@ -43,10 +44,8 @@ namespace Gfx {
*/
struct DeviceConfig
{
- //! Screen width
- int width;
- //! Screen height
- int height;
+ //! Screen size
+ Math::IntSize size;
//! Bits per pixel
int bpp;
//! Full screen
@@ -64,8 +63,7 @@ struct DeviceConfig
//! Loads the default values
inline void LoadDefault()
{
- width = 800;
- height = 600;
+ size = Math::IntSize(800, 600);
bpp = 32;
fullScreen = false;
resizeable = false;
diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h
index 787c2bf..8d6b082 100644
--- a/src/graphics/core/texture.h
+++ b/src/graphics/core/texture.h
@@ -18,6 +18,9 @@
#pragma once
+#include "math/intsize.h"
+
+
namespace Gfx {
/**
@@ -190,10 +193,8 @@ struct Texture
bool valid;
//! ID of the texture in graphics engine
unsigned int id;
- //! Width of texture
- int width;
- //! Height of texture
- int height;
+ //! Size of texture
+ Math::IntSize size;
//! Whether the texture has alpha channel
bool alpha;
@@ -201,7 +202,6 @@ struct Texture
{
valid = false;
id = 0;
- width = height = 0;
alpha = false;
}
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index 0914f9e..e544ee3 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -62,9 +62,6 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
m_sound = NULL;
m_terrain = NULL;
- m_dim.x = 640;
- m_dim.y = 480;
- m_lastDim = m_dim;
m_focus = 0.75f;
m_baseTime = 0;
m_lastTime = 0;
@@ -272,6 +269,12 @@ bool Gfx::CEngine::AfterDeviceSetInit()
return true;
}
+void Gfx::CEngine::ResetAfterDeviceChanged()
+{
+ // TODO
+}
+
+
Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams &params)
{
CImage img;
@@ -727,3 +730,14 @@ void Gfx::CEngine::AddStatisticTriangle(int count)
{
m_statisticTriangle += count;
}
+
+void Gfx::CEngine::SetShowStat(bool show)
+{
+ m_showStats = show;
+}
+
+bool Gfx::CEngine::GetShowStat()
+{
+ return m_showStats;
+}
+
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 1348cdd..25c5e5d 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -26,6 +26,7 @@
#include "graphics/core/texture.h"
#include "graphics/core/vertex.h"
#include "math/intpoint.h"
+#include "math/intsize.h"
#include "math/matrix.h"
#include "math/point.h"
#include "math/vector.h"
@@ -513,21 +514,33 @@ public:
CEngine(CInstanceManager *iMan, CApplication *app);
~CEngine();
+ //! Returns whether the device was initialized
bool GetWasInit();
+ //! Returns the last error encountered
std::string GetError();
+ //! Performs the first initialization, before a device was set
bool Create();
+ //! Frees all resources before exit
void Destroy();
+ //! Sets the device to be used
void SetDevice(Gfx::CDevice *device);
+ //! Returns the current device
Gfx::CDevice* GetDevice();
+ //! Performs initialization after a device was created and set
bool AfterDeviceSetInit();
+ //! Resets some states and flushes textures after device was changed (e.g. resoulution changed)
+ void ResetAfterDeviceChanged();
+
void SetTerrain(Gfx::CTerrain* terrain);
+ //! Processes incoming event
bool ProcessEvent(const Event &event);
+ //! Renders a single frame
bool Render();
@@ -859,6 +872,9 @@ protected:
bool m_wasInit;
std::string m_error;
+ //! Whether to show stats (FPS, etc)
+ bool m_showStats;
+
int m_blackSrcBlend[2];
int m_blackDestBlend[2];
int m_whiteSrcBlend[2];
@@ -887,8 +903,9 @@ protected:
bool m_render;
bool m_movieLock;
- Math::IntPoint m_dim;
- Math::IntPoint m_lastDim;
+ //! Current size of window
+ Math::IntSize m_size;
+ Math::IntSize m_lastSize;
std::vector<Gfx::EngineObjLevel1> m_objectTree;
std::vector<Gfx::EngineObject> m_objects;
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index bfe7fd7..1fd6a18 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -61,8 +61,9 @@ void Gfx::GLDeviceConfig::LoadDefault()
-Gfx::CGLDevice::CGLDevice()
+Gfx::CGLDevice::CGLDevice(const Gfx::GLDeviceConfig &config)
{
+ m_config = config;
m_wasInit = false;
m_lighting = false;
m_texturing = false;
@@ -86,18 +87,24 @@ std::string Gfx::CGLDevice::GetError()
bool Gfx::CGLDevice::Create()
{
#if defined(USE_GLEW)
- if (glewInit() != GLEW_OK)
- {
- m_error = "GLEW initialization failed";
- return false;
- }
+ static bool glewInited = false;
- if ( (! GLEW_ARB_multitexture) || (! GLEW_EXT_texture_env_combine) || (! GLEW_EXT_secondary_color) )
+ if (!glewInited)
{
- m_error = "GLEW reports required extensions not supported";
- return false;
- }
+ glewInited = true;
+
+ if (glewInit() != GLEW_OK)
+ {
+ m_error = "GLEW initialization failed";
+ return false;
+ }
+ if ( (! GLEW_ARB_multitexture) || (! GLEW_EXT_texture_env_combine) || (! GLEW_EXT_secondary_color) )
+ {
+ m_error = "GLEW reports required extensions not supported";
+ return false;
+ }
+ }
#endif
/* NOTE: when not using GLEW, extension testing is not performed, as it is assumed that
@@ -123,6 +130,8 @@ bool Gfx::CGLDevice::Create()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
+ glViewport(0, 0, m_config.size.w, m_config.size.h);
+
m_lights = std::vector<Gfx::Light>(GL_MAX_LIGHTS, Gfx::Light());
m_lightsEnabled = std::vector<bool> (GL_MAX_LIGHTS, false);
@@ -153,6 +162,17 @@ void Gfx::CGLDevice::Destroy()
m_wasInit = false;
}
+void Gfx::CGLDevice::ConfigChanged(const Gfx::GLDeviceConfig& newConfig)
+{
+ m_config = newConfig;
+
+ // Reset state
+ m_lighting = false;
+ m_texturing = false;
+ Destroy();
+ Create();
+}
+
void Gfx::CGLDevice::BeginScene()
{
Clear();
@@ -375,8 +395,8 @@ Gfx::Texture Gfx::CGLDevice::CreateTexture(CImage *image, const Gfx::TextureCrea
}
result.valid = true;
- result.width = data->surface->w;
- result.height = data->surface->h;
+ result.size.w = data->surface->w;
+ result.size.h = data->surface->h;
// Use & enable 1st texture stage
glActiveTexture(GL_TEXTURE0);
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index 313ea02..1864000 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -70,7 +70,7 @@ struct GLDevicePrivate;
class CGLDevice : public Gfx::CDevice
{
public:
- CGLDevice();
+ CGLDevice(const Gfx::GLDeviceConfig &config);
virtual ~CGLDevice();
virtual bool GetWasInit();
@@ -79,6 +79,8 @@ public:
virtual bool Create();
virtual void Destroy();
+ void ConfigChanged(const Gfx::GLDeviceConfig &newConfig);
+
virtual void BeginScene();
virtual void EndScene();
@@ -159,6 +161,8 @@ private:
void UpdateLightPosition(int index);
private:
+ //! Current config
+ Gfx::GLDeviceConfig m_config;
//! Was initialized?
bool m_wasInit;
//! Last encountered error
diff --git a/src/math/intsize.h b/src/math/intsize.h
new file mode 100644
index 0000000..f4b2431
--- /dev/null
+++ b/src/math/intsize.h
@@ -0,0 +1,61 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * 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 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+/** @defgroup MathIntSizeModule math/intsize.h
+ Contains the IntSize struct.
+ */
+
+#pragma once
+
+// Math module namespace
+namespace Math
+{
+
+/* @{ */ // start of group
+
+/** \struct IntSize math/size.h
+ \brief 2D size with integer dimensions */
+struct IntSize
+{
+ //! Width
+ int w;
+ //! Height
+ int h;
+
+ //! Constructs a zero size: (0,0)
+ inline IntSize()
+ {
+ LoadZero();
+ }
+
+ //! Constructs a size from given dimensions: (w,h)
+ inline explicit IntSize(int w, int h)
+ {
+ this->w = w;
+ this->h = h;
+ }
+
+ //! Sets the zero size: (0,0)
+ inline void LoadZero()
+ {
+ w = h = 0;
+ }
+}; // struct Size
+
+
+/* @} */ // end of group
+
+}; // namespace Math
diff --git a/src/math/size.h b/src/math/size.h
new file mode 100644
index 0000000..781b9a4
--- /dev/null
+++ b/src/math/size.h
@@ -0,0 +1,66 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * 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 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+/** @defgroup MathSizeModule math/size.h
+ Contains the Size struct.
+ */
+
+#pragma once
+
+// Math module namespace
+namespace Math
+{
+
+/* @{ */ // start of group
+
+/** \struct Size math/size.h
+ \brief 2D size
+
+ Represents a 2D size (w, h).
+ Is separate from Math::Point to avoid confusion.
+
+ */
+struct Size
+{
+ //! Width
+ float w;
+ //! Height
+ float h;
+
+ //! Constructs a zero size: (0,0)
+ inline Size()
+ {
+ LoadZero();
+ }
+
+ //! Constructs a size from given dimensions: (w,h)
+ inline explicit Size(float w, float h)
+ {
+ this->w = w;
+ this->h = h;
+ }
+
+ //! Sets the zero size: (0,0)
+ inline void LoadZero()
+ {
+ w = h = 0.0f;
+ }
+}; // struct Size
+
+
+/* @} */ // end of group
+
+}; // namespace Math