mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-19 12:39:42 +00:00
Have SDL manage the window instead of OGRE to work around SDL Windows bugs (grumble)
This commit is contained in:
parent
d26e33eb26
commit
043e29c620
5 changed files with 150 additions and 36 deletions
|
@ -1,7 +1,5 @@
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
#include "components/esm/loadcell.hpp"
|
#include "components/esm/loadcell.hpp"
|
||||||
|
|
||||||
#include <OgreRoot.h>
|
#include <OgreRoot.h>
|
||||||
|
@ -40,6 +38,7 @@
|
||||||
#include "mwmechanics/mechanicsmanagerimp.hpp"
|
#include "mwmechanics/mechanicsmanagerimp.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
void OMW::Engine::executeLocalScripts()
|
void OMW::Engine::executeLocalScripts()
|
||||||
{
|
{
|
||||||
|
@ -70,6 +69,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
handleSDLMessages();
|
||||||
|
|
||||||
mEnvironment.setFrameDuration (evt.timeSinceLastFrame);
|
mEnvironment.setFrameDuration (evt.timeSinceLastFrame);
|
||||||
|
|
||||||
// update input
|
// update input
|
||||||
|
@ -116,6 +117,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);
|
MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->onFrame(evt.timeSinceLastFrame);
|
MWBase::Environment::get().getWindowManager()->onFrame(evt.timeSinceLastFrame);
|
||||||
|
|
||||||
|
//Flush any events that weren't handled this frame
|
||||||
|
SDL_FlushEvents(0x0, 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -125,6 +129,65 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OMW::Engine::handleSDLMessages()
|
||||||
|
{
|
||||||
|
//Pump messages since the last frame
|
||||||
|
const int max_events = 20;
|
||||||
|
SDL_Event events[max_events];
|
||||||
|
|
||||||
|
SDL_PumpEvents();
|
||||||
|
int num_events = SDL_PeepEvents(events, max_events, SDL_PEEKEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT);
|
||||||
|
|
||||||
|
bool move_or_resize = false;
|
||||||
|
|
||||||
|
unsigned int size_x = 0;
|
||||||
|
unsigned int size_y = 0;
|
||||||
|
|
||||||
|
if(num_events != 0)
|
||||||
|
{
|
||||||
|
for(int i=0; i < num_events; ++i)
|
||||||
|
{
|
||||||
|
switch(events[i].window.event)
|
||||||
|
{
|
||||||
|
case SDL_WINDOWEVENT_RESIZED:
|
||||||
|
case SDL_WINDOWEVENT_MOVED:
|
||||||
|
printf("Resizing window!\n");
|
||||||
|
move_or_resize = true;
|
||||||
|
size_x = events[i].window.data1;
|
||||||
|
size_y = events[i].window.data2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//handle window movements
|
||||||
|
if(move_or_resize)
|
||||||
|
{
|
||||||
|
mOgre->adjustViewport();
|
||||||
|
if(!mOgre->getWindow()->isFullScreen())
|
||||||
|
{
|
||||||
|
SDL_DisplayMode dispMode;
|
||||||
|
SDL_Window* sdlWindow = mOgre->getSDLWindow();
|
||||||
|
|
||||||
|
SDL_GetWindowDisplayMode(sdlWindow, &dispMode);
|
||||||
|
|
||||||
|
dispMode.w = size_x;
|
||||||
|
dispMode.h = size_y;
|
||||||
|
|
||||||
|
SDL_SetWindowDisplayMode(sdlWindow, &dispMode);
|
||||||
|
|
||||||
|
mOgre->getWindow()->windowMovedOrResized();
|
||||||
|
mOgre->getWindow()->resize(size_x, size_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_QUIT, SDL_QUIT) != 0)
|
||||||
|
{
|
||||||
|
//user requested a quit, break out.
|
||||||
|
mOgre->getRoot()->queueEndRendering();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||||
: mOgre (0)
|
: mOgre (0)
|
||||||
, mFpsLevel(0)
|
, mFpsLevel(0)
|
||||||
|
@ -140,6 +203,16 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||||
{
|
{
|
||||||
std::srand ( std::time(NULL) );
|
std::srand ( std::time(NULL) );
|
||||||
MWClass::registerClasses();
|
MWClass::registerClasses();
|
||||||
|
|
||||||
|
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE;
|
||||||
|
if(SDL_WasInit(flags) == 0)
|
||||||
|
{
|
||||||
|
//kindly ask SDL not to trash our OGL context
|
||||||
|
//might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ?
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||||||
|
if(SDL_Init(flags) != 0)
|
||||||
|
throw std::runtime_error("Couldn't initialize SDL!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OMW::Engine::~Engine()
|
OMW::Engine::~Engine()
|
||||||
|
@ -147,6 +220,7 @@ OMW::Engine::~Engine()
|
||||||
mEnvironment.cleanup();
|
mEnvironment.cleanup();
|
||||||
delete mScriptContext;
|
delete mScriptContext;
|
||||||
delete mOgre;
|
delete mOgre;
|
||||||
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all BSA files in data directory.
|
// Load all BSA files in data directory.
|
||||||
|
@ -317,7 +391,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
addResourcesDirectory(mResDir / "shadows");
|
addResourcesDirectory(mResDir / "shadows");
|
||||||
addZipResource(mResDir / "mygui" / "Obliviontt.zip");
|
addZipResource(mResDir / "mygui" / "Obliviontt.zip");
|
||||||
|
|
||||||
// Create the window
|
|
||||||
OEngine::Render::WindowSettings windowSettings;
|
OEngine::Render::WindowSettings windowSettings;
|
||||||
windowSettings.fullscreen = settings.getBool("fullscreen", "Video");
|
windowSettings.fullscreen = settings.getBool("fullscreen", "Video");
|
||||||
windowSettings.window_x = settings.getInt("resolution x", "Video");
|
windowSettings.window_x = settings.getInt("resolution x", "Video");
|
||||||
|
@ -325,20 +398,11 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
windowSettings.vsync = settings.getBool("vsync", "Video");
|
windowSettings.vsync = settings.getBool("vsync", "Video");
|
||||||
std::string aa = settings.getString("antialiasing", "Video");
|
std::string aa = settings.getString("antialiasing", "Video");
|
||||||
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
|
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
|
||||||
|
|
||||||
mOgre->createWindow("OpenMW", windowSettings);
|
mOgre->createWindow("OpenMW", windowSettings);
|
||||||
|
|
||||||
loadBSA();
|
loadBSA();
|
||||||
|
|
||||||
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE;
|
|
||||||
if(SDL_WasInit(flags) == 0)
|
|
||||||
{
|
|
||||||
//kindly ask SDL not to trash our OGL context
|
|
||||||
//might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ?
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
|
||||||
if(SDL_Init(flags) != 0)
|
|
||||||
throw std::runtime_error("Couldn't initialize SDL!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
|
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
|
||||||
MWGui::CursorReplace replacer;
|
MWGui::CursorReplace replacer;
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,8 @@ namespace OMW
|
||||||
|
|
||||||
void executeLocalScripts();
|
void executeLocalScripts();
|
||||||
|
|
||||||
|
void handleSDLMessages();
|
||||||
|
|
||||||
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
|
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
|
||||||
|
|
||||||
/// Load settings from various files, returns the path to the user settings file
|
/// Load settings from various files, returns the path to the user settings file
|
||||||
|
|
23
extern/sdl4ogre/sdlinputwrapper.cpp
vendored
23
extern/sdl4ogre/sdlinputwrapper.cpp
vendored
|
@ -85,7 +85,6 @@ namespace SFO
|
||||||
mSDLWindow = NULL;
|
mSDLWindow = NULL;
|
||||||
|
|
||||||
SDL_StopTextInput();
|
SDL_StopTextInput();
|
||||||
SDL_Quit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputWrapper::capture()
|
void InputWrapper::capture()
|
||||||
|
@ -121,24 +120,6 @@ namespace SFO
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
mKeyboardListener->keyReleased(evt.key);
|
mKeyboardListener->keyReleased(evt.key);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
|
||||||
mWindowListener->windowFocusChange(true);
|
|
||||||
break;
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
|
||||||
mWindowListener->windowFocusChange(false);
|
|
||||||
break;
|
|
||||||
case SDL_WINDOWEVENT_EXPOSED:
|
|
||||||
mWindowListener->windowVisibilityChange(true);
|
|
||||||
break;
|
|
||||||
case SDL_WINDOWEVENT_HIDDEN:
|
|
||||||
mWindowListener->windowVisibilityChange(false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
//SDL traps ^C signals, pass it to OGRE.
|
|
||||||
case SDL_QUIT:
|
|
||||||
Ogre::Root::getSingleton().queueEndRendering();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,9 +167,7 @@ namespace SFO
|
||||||
|
|
||||||
//now remove all mouse events using the old setting from the queue
|
//now remove all mouse events using the old setting from the queue
|
||||||
SDL_PumpEvents();
|
SDL_PumpEvents();
|
||||||
|
SDL_FlushEvent(SDL_MOUSEMOTION);
|
||||||
SDL_Event dummy[20];
|
|
||||||
SDL_PeepEvents(dummy, 20, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Internal method for ignoring relative motions as a side effect
|
/// \brief Internal method for ignoring relative motions as a side effect
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
#include "fader.hpp"
|
#include "fader.hpp"
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_syswm.h>
|
||||||
|
|
||||||
#include "OgreRoot.h"
|
#include "OgreRoot.h"
|
||||||
#include "OgreRenderWindow.h"
|
#include "OgreRenderWindow.h"
|
||||||
#include "OgreLogManager.h"
|
#include "OgreLogManager.h"
|
||||||
|
@ -47,11 +50,16 @@ void OgreRenderer::cleanup()
|
||||||
delete mRoot;
|
delete mRoot;
|
||||||
mRoot = NULL;
|
mRoot = NULL;
|
||||||
|
|
||||||
|
SDL_DestroyWindow(mSDLWindow);
|
||||||
|
mSDLWindow = NULL;
|
||||||
|
|
||||||
unloadPlugins();
|
unloadPlugins();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreRenderer::start()
|
void OgreRenderer::start()
|
||||||
{
|
{
|
||||||
|
//TODO: Check if we still need to do this if we're using SDL's
|
||||||
|
//message pump
|
||||||
#if defined(__APPLE__) && !defined(__LP64__)
|
#if defined(__APPLE__) && !defined(__LP64__)
|
||||||
// OSX Carbon Message Pump
|
// OSX Carbon Message Pump
|
||||||
do {
|
do {
|
||||||
|
@ -214,6 +222,56 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings&
|
||||||
params.insert(std::make_pair("FSAA", settings.fsaa));
|
params.insert(std::make_pair("FSAA", settings.fsaa));
|
||||||
params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false"));
|
params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false"));
|
||||||
|
|
||||||
|
// Create an application window with the following settings:
|
||||||
|
SDL_Window *window = SDL_CreateWindow(
|
||||||
|
"OpenMW", // window title
|
||||||
|
SDL_WINDOWPOS_UNDEFINED, // initial x position
|
||||||
|
SDL_WINDOWPOS_UNDEFINED, // initial y position
|
||||||
|
settings.window_x, // width, in pixels
|
||||||
|
settings.window_y, // height, in pixels
|
||||||
|
SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE
|
||||||
|
| (settings.fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//get the native whnd
|
||||||
|
struct SDL_SysWMinfo wmInfo;
|
||||||
|
SDL_VERSION(&wmInfo.version);
|
||||||
|
|
||||||
|
if(-1 == SDL_GetWindowWMInfo(window, &wmInfo))
|
||||||
|
throw std::runtime_error("Couldn't get WM Info!");
|
||||||
|
|
||||||
|
Ogre::String winHandle;
|
||||||
|
|
||||||
|
switch(wmInfo.subsystem)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
case SDL_SYSWM_WINDOWS:
|
||||||
|
// Windows code
|
||||||
|
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.win.window);
|
||||||
|
break;
|
||||||
|
#elif MACOS
|
||||||
|
case SDL_SYSWM_COCOA:
|
||||||
|
//required to make OGRE play nice with our window
|
||||||
|
params.insert(std::make_pair("macAPI", "cocoa"));
|
||||||
|
params.insert(std::make_pair("macAPICocoaUseNSView", "true"));
|
||||||
|
|
||||||
|
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.cocoa.window);
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
case SDL_SYSWM_X11:
|
||||||
|
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.display);
|
||||||
|
winHandle += ":0:";
|
||||||
|
winHandle += Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.window);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Unexpected WM!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.insert(std::make_pair("externalWindowHandle", winHandle));
|
||||||
|
|
||||||
mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms);
|
mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms);
|
||||||
|
|
||||||
// create the semi-transparent black background texture used by the GUI.
|
// create the semi-transparent black background texture used by the GUI.
|
||||||
|
@ -253,7 +311,11 @@ void OgreRenderer::createScene(const std::string& camName, float fov, float near
|
||||||
void OgreRenderer::adjustViewport()
|
void OgreRenderer::adjustViewport()
|
||||||
{
|
{
|
||||||
// Alter the camera aspect ratio to match the viewport
|
// Alter the camera aspect ratio to match the viewport
|
||||||
mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight()));
|
if(mCamera != NULL)
|
||||||
|
{
|
||||||
|
mView->setDimensions(0, 0, 1, 1);
|
||||||
|
mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener)
|
void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener)
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include <OgreRoot.h>
|
#include <OgreRoot.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct SDL_Window;
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
#if !defined(__APPLE__) || defined(__LP64__)
|
#if !defined(__APPLE__) || defined(__LP64__)
|
||||||
|
@ -74,6 +76,7 @@ namespace OEngine
|
||||||
Ogre::Root *mRoot;
|
Ogre::Root *mRoot;
|
||||||
#endif
|
#endif
|
||||||
Ogre::RenderWindow *mWindow;
|
Ogre::RenderWindow *mWindow;
|
||||||
|
SDL_Window *mSDLWindow;
|
||||||
Ogre::SceneManager *mScene;
|
Ogre::SceneManager *mScene;
|
||||||
Ogre::Camera *mCamera;
|
Ogre::Camera *mCamera;
|
||||||
Ogre::Viewport *mView;
|
Ogre::Viewport *mView;
|
||||||
|
@ -99,6 +102,7 @@ namespace OEngine
|
||||||
OgreRenderer()
|
OgreRenderer()
|
||||||
: mRoot(NULL)
|
: mRoot(NULL)
|
||||||
, mWindow(NULL)
|
, mWindow(NULL)
|
||||||
|
, mSDLWindow(NULL)
|
||||||
, mScene(NULL)
|
, mScene(NULL)
|
||||||
, mCamera(NULL)
|
, mCamera(NULL)
|
||||||
, mView(NULL)
|
, mView(NULL)
|
||||||
|
@ -169,6 +173,9 @@ namespace OEngine
|
||||||
/// Get the rendering window
|
/// Get the rendering window
|
||||||
Ogre::RenderWindow *getWindow() { return mWindow; }
|
Ogre::RenderWindow *getWindow() { return mWindow; }
|
||||||
|
|
||||||
|
/// Get the SDL Window
|
||||||
|
SDL_Window *getSDLWindow() { return mSDLWindow; }
|
||||||
|
|
||||||
/// Get the scene manager
|
/// Get the scene manager
|
||||||
Ogre::SceneManager *getScene() { return mScene; }
|
Ogre::SceneManager *getScene() { return mScene; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue