forked from teamnwah/openmw-tes3coop
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
apps/openmw
extern/sdl4ogre
libs/openengine/ogre
|
@ -1,7 +1,5 @@
|
|||
#include "engine.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "components/esm/loadcell.hpp"
|
||||
|
||||
#include <OgreRoot.h>
|
||||
|
@ -40,6 +38,7 @@
|
|||
#include "mwmechanics/mechanicsmanagerimp.hpp"
|
||||
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
void OMW::Engine::executeLocalScripts()
|
||||
{
|
||||
|
@ -70,6 +69,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
{
|
||||
try
|
||||
{
|
||||
handleSDLMessages();
|
||||
|
||||
mEnvironment.setFrameDuration (evt.timeSinceLastFrame);
|
||||
|
||||
// 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()->onFrame(evt.timeSinceLastFrame);
|
||||
|
||||
//Flush any events that weren't handled this frame
|
||||
SDL_FlushEvents(0x0, 0xFFFFFFFF);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
@ -125,6 +129,65 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
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)
|
||||
: mOgre (0)
|
||||
, mFpsLevel(0)
|
||||
|
@ -140,6 +203,16 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
|||
{
|
||||
std::srand ( std::time(NULL) );
|
||||
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()
|
||||
|
@ -147,6 +220,7 @@ OMW::Engine::~Engine()
|
|||
mEnvironment.cleanup();
|
||||
delete mScriptContext;
|
||||
delete mOgre;
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
// Load all BSA files in data directory.
|
||||
|
@ -317,7 +391,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
addResourcesDirectory(mResDir / "shadows");
|
||||
addZipResource(mResDir / "mygui" / "Obliviontt.zip");
|
||||
|
||||
// Create the window
|
||||
OEngine::Render::WindowSettings windowSettings;
|
||||
windowSettings.fullscreen = settings.getBool("fullscreen", "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");
|
||||
std::string aa = settings.getString("antialiasing", "Video");
|
||||
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
|
||||
|
||||
mOgre->createWindow("OpenMW", windowSettings);
|
||||
|
||||
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)
|
||||
MWGui::CursorReplace replacer;
|
||||
|
||||
|
|
|
@ -103,6 +103,8 @@ namespace OMW
|
|||
|
||||
void executeLocalScripts();
|
||||
|
||||
void handleSDLMessages();
|
||||
|
||||
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
|
||||
|
||||
/// 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;
|
||||
|
||||
SDL_StopTextInput();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void InputWrapper::capture()
|
||||
|
@ -121,24 +120,6 @@ namespace SFO
|
|||
case SDL_KEYUP:
|
||||
mKeyboardListener->keyReleased(evt.key);
|
||||
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
|
||||
SDL_PumpEvents();
|
||||
|
||||
SDL_Event dummy[20];
|
||||
SDL_PeepEvents(dummy, 20, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION);
|
||||
SDL_FlushEvent(SDL_MOUSEMOTION);
|
||||
}
|
||||
|
||||
/// \brief Internal method for ignoring relative motions as a side effect
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "renderer.hpp"
|
||||
#include "fader.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#include "OgreRoot.h"
|
||||
#include "OgreRenderWindow.h"
|
||||
#include "OgreLogManager.h"
|
||||
|
@ -47,11 +50,16 @@ void OgreRenderer::cleanup()
|
|||
delete mRoot;
|
||||
mRoot = NULL;
|
||||
|
||||
SDL_DestroyWindow(mSDLWindow);
|
||||
mSDLWindow = NULL;
|
||||
|
||||
unloadPlugins();
|
||||
}
|
||||
|
||||
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__)
|
||||
// OSX Carbon Message Pump
|
||||
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("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);
|
||||
|
||||
// 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()
|
||||
{
|
||||
// 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)
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <OgreRoot.h>
|
||||
#endif
|
||||
|
||||
struct SDL_Window;
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
#if !defined(__APPLE__) || defined(__LP64__)
|
||||
|
@ -74,6 +76,7 @@ namespace OEngine
|
|||
Ogre::Root *mRoot;
|
||||
#endif
|
||||
Ogre::RenderWindow *mWindow;
|
||||
SDL_Window *mSDLWindow;
|
||||
Ogre::SceneManager *mScene;
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::Viewport *mView;
|
||||
|
@ -99,6 +102,7 @@ namespace OEngine
|
|||
OgreRenderer()
|
||||
: mRoot(NULL)
|
||||
, mWindow(NULL)
|
||||
, mSDLWindow(NULL)
|
||||
, mScene(NULL)
|
||||
, mCamera(NULL)
|
||||
, mView(NULL)
|
||||
|
@ -169,6 +173,9 @@ namespace OEngine
|
|||
/// Get the rendering window
|
||||
Ogre::RenderWindow *getWindow() { return mWindow; }
|
||||
|
||||
/// Get the SDL Window
|
||||
SDL_Window *getSDLWindow() { return mSDLWindow; }
|
||||
|
||||
/// Get the scene manager
|
||||
Ogre::SceneManager *getScene() { return mScene; }
|
||||
|
||||
|
|
Loading…
Reference in a new issue