diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 7498044ab..895970696 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -63,6 +63,10 @@ opencs_units (view/world scenetoolmode ) +opencs_units (view/render + scenewidget + ) + opencs_units_noqt (view/world dialoguesubview subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index e879cb25e..1c1e37c2d 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -6,9 +6,11 @@ #include #include +#include +#include + #include "model/doc/document.hpp" #include "model/world/data.hpp" -#include CS::Editor::Editor() : mDocumentManager (mCfgMgr), mViewManager (mDocumentManager) @@ -212,6 +214,20 @@ int CS::Editor::run() if (mLocal.empty()) return 1; + // TODO: setting + Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem")); + + Ogre::Root::getSingleton().initialise(false); + + // Create a hidden background window to keep resources + Ogre::NameValuePairList params; + params.insert(std::make_pair("title", "")); + params.insert(std::make_pair("FSAA", "0")); + params.insert(std::make_pair("vsync", "false")); + params.insert(std::make_pair("hidden", "true")); + Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, ¶ms); + hiddenWindow->setActive(false); + mStartup.show(); QApplication::setQuitOnLastWindowClosed (true); diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index e5e7514ce..449dd229e 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -7,6 +7,8 @@ #include #include +#include + class Application : public QApplication { private: @@ -33,6 +35,12 @@ class Application : public QApplication int main(int argc, char *argv[]) { Q_INIT_RESOURCE (resources); + + // TODO: Ogre startup shouldn't be here, but it currently has to: + // SceneWidget destructor will delete the created render window, which would be called _after_ Root has shut down :( + OgreInit::OgreInit ogreInit; + ogreInit.init("./opencsOgre.log"); // TODO log path? + Application mApplication (argc, argv); mApplication.setWindowIcon (QIcon (":./opencs.png")); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp new file mode 100644 index 000000000..c8b37e9bb --- /dev/null +++ b/apps/opencs/view/render/scenewidget.cpp @@ -0,0 +1,128 @@ +#include "scenewidget.hpp" + +#include +#include + +#include +#include +#include + +namespace CSVRender +{ + + SceneWidget::SceneWidget(QWidget *parent) + : QWidget(parent) + , mWindow(NULL) + , mCamera(NULL) + , mSceneMgr(NULL) + { + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_NoSystemBackground); + + mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); + + // Throw in a random color just to make sure multiple scenes work + Ogre::Real r = Ogre::Math::RangeRandom(0, 1); + Ogre::Real g = Ogre::Math::RangeRandom(0, 1); + Ogre::Real b = Ogre::Math::RangeRandom(0, 1); + mSceneMgr->setAmbientLight(Ogre::ColourValue(r,g,b,1)); + + Ogre::Light* l = mSceneMgr->createLight(); + l->setType (Ogre::Light::LT_DIRECTIONAL); + l->setDirection (Ogre::Vector3(-0.4, -0.7, 0.3)); + l->setDiffuseColour (Ogre::ColourValue(0.7,0.7,0.7)); + + mCamera = mSceneMgr->createCamera("foo"); + + Ogre::Entity* ent = mSceneMgr->createEntity("cube", Ogre::SceneManager::PT_CUBE); + ent->setMaterialName("BaseWhite"); + + mSceneMgr->getRootSceneNode()->attachObject(ent); + + mCamera->setPosition(300,300,300); + mCamera->lookAt(0,0,0); + mCamera->setNearClipDistance(0.1); + mCamera->setFarClipDistance(3000); + } + + void SceneWidget::updateOgreWindow() + { + if (mWindow) + { + Ogre::Root::getSingleton().destroyRenderTarget(mWindow); + mWindow = NULL; + } + + std::stringstream windowHandle; + windowHandle << this->winId(); + + std::stringstream windowTitle; + static int count=0; + windowTitle << ++count; + + Ogre::NameValuePairList params; + + params.insert(std::make_pair("externalWindowHandle", windowHandle.str())); + params.insert(std::make_pair("title", windowTitle.str())); + params.insert(std::make_pair("FSAA", "0")); // TODO setting + params.insert(std::make_pair("vsync", "false")); // TODO setting + + mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, ¶ms); + mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3,0.3,0.3,1)); + + Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height()); + mCamera->setAspectRatio(aspectRatio); + } + + SceneWidget::~SceneWidget() + { + Ogre::Root::getSingleton().destroyRenderTarget(mWindow); + } + + void SceneWidget::paintEvent(QPaintEvent* e) + { + if (!mWindow) + updateOgreWindow(); + + mWindow->update(); + e->accept(); + } + + + QPaintEngine* SceneWidget::paintEngine() const + { + // We don't want another paint engine to get in the way. + // So we return nothing. + return NULL; + } + + void SceneWidget::resizeEvent(QResizeEvent *e) + { + if (!mWindow) + return; + + const QSize &newSize = e->size(); + + // TODO: Fix Ogre to handle this more consistently (fixed in 1.9) +#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX + mWindow->resize(newSize.width(), newSize.height()); +#else + mWindow->windowMovedOrResized(); +#endif + + Ogre::Real aspectRatio = Ogre::Real(newSize.width()) / Ogre::Real(newSize.height()); + mCamera->setAspectRatio(aspectRatio); + } + + bool SceneWidget::event(QEvent *e) + { + if (e->type() == QEvent::WinIdChange) + { + // I haven't actually seen this happen yet. + if (mWindow) + updateOgreWindow(); + } + return QWidget::event(e); + } + +} diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp new file mode 100644 index 000000000..355a6331e --- /dev/null +++ b/apps/opencs/view/render/scenewidget.hpp @@ -0,0 +1,40 @@ +#ifndef OPENCS_VIEW_SCENEWIDGET_H +#define OPENCS_VIEW_SCENEWIDGET_H + +#include + +namespace Ogre +{ + class Camera; + class SceneManager; + class RenderWindow; +} + +namespace CSVRender +{ + + class SceneWidget : public QWidget + { + Q_OBJECT + + public: + SceneWidget(QWidget *parent); + virtual ~SceneWidget(void); + + QPaintEngine* paintEngine() const; + + private: + void paintEvent(QPaintEvent* e); + void resizeEvent(QResizeEvent* e); + bool event(QEvent* e); + + void updateOgreWindow(); + + Ogre::Camera* mCamera; + Ogre::SceneManager* mSceneMgr; + Ogre::RenderWindow* mWindow; + }; + +} + +#endif diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index e3618c549..83b30be13 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -9,6 +9,8 @@ #include "../filter/filterbox.hpp" +#include "../render/scenewidget.hpp" + #include "tablebottombox.hpp" #include "creator.hpp" #include "scenetoolbar.hpp" @@ -41,15 +43,10 @@ toolbar->addTool (new SceneToolMode (toolbar)); toolbar->addTool (new SceneToolMode (toolbar)); layout2->addWidget (toolbar, 0); - /// \todo replace with rendering widget - QPalette palette2 (palette()); - palette2.setColor (QPalette::Background, Qt::white); - QLabel *placeholder = new QLabel ("Here goes the 3D scene", this); - placeholder->setAutoFillBackground (true); - placeholder->setPalette (palette2); - placeholder->setAlignment (Qt::AlignHCenter); - layout2->addWidget (placeholder, 1); + CSVRender::SceneWidget* sceneWidget = new CSVRender::SceneWidget(this); + + layout2->addWidget (sceneWidget, 1); layout->insertLayout (0, layout2, 1); @@ -79,4 +76,4 @@ void CSVWorld::SceneSubView::updateEditorSetting(const QString &settingName, con void CSVWorld::SceneSubView::setStatusBar (bool show) { mBottom->setStatusBar (show); -} \ No newline at end of file +} diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index e7cbd549c..5c0eff1c0 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -127,7 +127,7 @@ namespace SFO case SDL_WINDOWEVENT_SIZE_CHANGED: int w,h; SDL_GetWindowSize(mSDLWindow, &w, &h); - // TODO: Fix Ogre to handle this more consistently + // TODO: Fix Ogre to handle this more consistently (fixed in 1.9) #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX mOgreWindow->resize(w, h); #else @@ -138,7 +138,7 @@ namespace SFO break; case SDL_WINDOWEVENT_RESIZED: - // TODO: Fix Ogre to handle this more consistently + // TODO: Fix Ogre to handle this more consistently (fixed in 1.9) #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX mOgreWindow->resize(evt.window.data1, evt.window.data2); #else