From c36dfef972b858d0b640f0bb0f1f0604c685dce2 Mon Sep 17 00:00:00 2001
From: Marc Zinnschlag <marc@zpages.de>
Date: Sun, 16 Mar 2014 12:44:01 +0100
Subject: [PATCH] prewview subview

---
 apps/opencs/CMakeLists.txt                |  8 +++-
 apps/opencs/editor.cpp                    | 47 +++++++++++++++++++--
 apps/opencs/editor.hpp                    |  8 ++++
 apps/opencs/main.cpp                      |  6 +++
 apps/opencs/view/render/previewwidget.cpp | 45 ++++++++++++++++++++
 apps/opencs/view/render/previewwidget.hpp | 42 +++++++++++++++++++
 apps/opencs/view/world/previewsubview.cpp | 50 +++++++++++++++++++++++
 apps/opencs/view/world/previewsubview.hpp | 36 ++++++++++++++++
 apps/opencs/view/world/subviews.cpp       |  3 ++
 9 files changed, 240 insertions(+), 5 deletions(-)
 create mode 100644 apps/opencs/view/render/previewwidget.cpp
 create mode 100644 apps/opencs/view/render/previewwidget.hpp
 create mode 100644 apps/opencs/view/world/previewsubview.cpp
 create mode 100644 apps/opencs/view/world/previewsubview.hpp

diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt
index 621b9bf86..7cdaad5be 100644
--- a/apps/opencs/CMakeLists.txt
+++ b/apps/opencs/CMakeLists.txt
@@ -60,11 +60,12 @@ opencs_hdrs_noqt (view/doc
 opencs_units (view/world
     table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
     cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
-    scenetoolmode infocreator scriptedit
+    scenetoolmode infocreator scriptedit previewsubview
     )
 
 opencs_units (view/render
     scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
+    previewwidget
     )
 
 opencs_units_noqt (view/render
@@ -147,6 +148,9 @@ if(WIN32)
     set(QT_USE_QTMAIN TRUE)
 endif(WIN32)
 
+set(BOOST_COMPONENTS system filesystem program_options thread wave)
+find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
+
 find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
 include(${QT_USE_FILE})
 
@@ -187,6 +191,8 @@ if(APPLE)
 endif(APPLE)
 
 target_link_libraries(opencs
+    ${OGRE_LIBRARIES}
+    ${SHINY_LIBRARIES}
     ${Boost_LIBRARIES}
     ${QT_LIBRARIES}
     components
diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp
index 9eb95fafa..942780c32 100644
--- a/apps/opencs/editor.cpp
+++ b/apps/opencs/editor.cpp
@@ -9,6 +9,9 @@
 #include <OgreRoot.h>
 #include <OgreRenderWindow.h>
 
+#include <extern/shiny/Main/Factory.hpp>
+#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
+
 #include <components/ogreinit/ogreinit.hpp>
 
 #include <components/bsa/resources.hpp>
@@ -81,7 +84,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
 
     mCfgMgr.readConfiguration(variables, desc);
 
-    mDocumentManager.setResourceDir (variables["resources"].as<std::string>());
+    mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
 
     mFsStrict = variables["fs-strict"].as<bool>();
 
@@ -225,6 +228,15 @@ int CS::Editor::run()
     if (mLocal.empty())
         return 1;
 
+    mStartup.show();
+
+    QApplication::setQuitOnLastWindowClosed (true);
+
+    return QApplication::exec();
+}
+
+std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
+{
     // TODO: setting
     Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
 
@@ -242,9 +254,36 @@ int CS::Editor::run()
     Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params);
     hiddenWindow->setActive(false);
 
-    mStartup.show();
+    sh::OgrePlatform* platform =
+        new sh::OgrePlatform ("General", (mResources / "materials").string());
 
-    QApplication::setQuitOnLastWindowClosed (true);
+    if (!boost::filesystem::exists (mCfgMgr.getCachePath()))
+        boost::filesystem::create_directories (mCfgMgr.getCachePath());
 
-    return QApplication::exec();
+    platform->setCacheFolder (mCfgMgr.getCachePath().string());
+
+    std::auto_ptr<sh::Factory> factory (new sh::Factory (platform));
+
+    factory->setCurrentLanguage (sh::Language_GLSL); /// \todo make this configurable
+    factory->setWriteSourceCache (true);
+    factory->setReadSourceCache (true);
+    factory->setReadMicrocodeCache (true);
+    factory->setWriteMicrocodeCache (true);
+
+    factory->loadAllFiles();
+
+    sh::Factory::getInstance().setGlobalSetting ("fog", "true");
+
+    sh::Factory::getInstance().setGlobalSetting ("shadows", "false");
+    sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", "false");
+
+    sh::Factory::getInstance ().setGlobalSetting ("render_refraction", "false");
+
+    sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false");
+
+    sh::Factory::getInstance ().setGlobalSetting ("num_lights", "8");
+
+    /// \todo add more configurable shiny settings
+
+    return factory;
 }
diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp
index ec417ba8e..164398fb7 100644
--- a/apps/opencs/editor.hpp
+++ b/apps/opencs/editor.hpp
@@ -1,11 +1,15 @@
 #ifndef CS_EDITOR_H
 #define CS_EDITOR_H
 
+#include <memory>
+
 #include <QObject>
 #include <QString>
 #include <QLocalServer>
 #include <QLocalSocket>
 
+#include <extern/shiny/Main/Factory.hpp>
+
 #ifndef Q_MOC_RUN
 #include <components/files/configurationmanager.hpp>
 #endif
@@ -42,6 +46,7 @@ namespace CS
             CSVSettings::UserSettingsDialog mSettings;
             CSVDoc::FileDialog mFileDialog;
             boost::filesystem::path mLocal;
+            boost::filesystem::path mResources;
             bool mFsStrict;
 
             void setupDataFiles (const Files::PathContainer& dataDirs);
@@ -63,6 +68,9 @@ namespace CS
             int run();
             ///< \return error status
 
+            std::auto_ptr<sh::Factory> setupGraphics();
+            ///< The returned factory must persist at least as long as *this.
+
         private slots:
 
             void createGame();
diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp
index 212ed0836..eded36394 100644
--- a/apps/opencs/main.cpp
+++ b/apps/opencs/main.cpp
@@ -7,6 +7,8 @@
 #include <QApplication>
 #include <QIcon>
 
+#include <extern/shiny/Main/Factory.hpp>
+
 #include <components/ogreinit/ogreinit.hpp>
 
 #ifdef Q_OS_MAC
@@ -42,6 +44,8 @@ int main(int argc, char *argv[])
 
     OgreInit::OgreInit ogreInit;
 
+    std::auto_ptr<sh::Factory> shinyFactory;
+
     Application application (argc, argv);
 
 #ifdef Q_OS_MAC
@@ -73,5 +77,7 @@ int main(int argc, char *argv[])
        // return 0;
     }
 
+    shinyFactory = editor.setupGraphics();
+
     return editor.run();
 }
diff --git a/apps/opencs/view/render/previewwidget.cpp b/apps/opencs/view/render/previewwidget.cpp
new file mode 100644
index 000000000..160240b17
--- /dev/null
+++ b/apps/opencs/view/render/previewwidget.cpp
@@ -0,0 +1,45 @@
+
+#include "previewwidget.hpp"
+
+#include <OgreSceneManager.h>
+
+#include "../../model/world/data.hpp"
+
+void CSVRender::PreviewWidget::setup (const std::string& id)
+{
+    setNavigation (&mOrbit);
+
+    int column = mData.getReferenceables().findColumnIndex (CSMWorld::Columns::ColumnId_Model);
+
+    int row = mData.getReferenceables().getIndex (id);
+
+    QVariant value = mData.getReferenceables().getData (row, column);
+
+    if (!value.isValid())
+        return;
+
+    std::string model = value.toString().toUtf8().constData();
+
+    if (model.empty())
+        return;
+
+    Ogre::SceneNode* node = getSceneManager()->getRootSceneNode()->createChildSceneNode();
+    node->setPosition (Ogre::Vector3 (0, 0, 0));
+
+    mObject = NifOgre::Loader::createObjects (node, "Meshes\\" + model);
+}
+
+CSVRender::PreviewWidget::PreviewWidget (const CSMWorld::Data& data,
+    const std::string& referenceableId, QWidget *parent)
+: SceneWidget (parent), mData (data)
+{
+    setup (referenceableId);
+}
+
+CSVRender::PreviewWidget::PreviewWidget (const CSMWorld::Data& data,
+    const std::string& referenceableId, const std::string& referenceId, QWidget *parent)
+: SceneWidget (parent), mData (data)
+{
+    setup (referenceableId);
+    /// \todo apply reference modifications (scale, rotation)
+}
diff --git a/apps/opencs/view/render/previewwidget.hpp b/apps/opencs/view/render/previewwidget.hpp
new file mode 100644
index 000000000..01d40050f
--- /dev/null
+++ b/apps/opencs/view/render/previewwidget.hpp
@@ -0,0 +1,42 @@
+#ifndef OPENCS_VIEW_PREVIEWWIDGET_H
+#define OPENCS_VIEW_PREVIEWWIDGET_H
+
+#include <components/nifogre/ogrenifloader.hpp>
+
+#include "scenewidget.hpp"
+
+#include "navigationorbit.hpp"
+
+namespace CSMWorld
+{
+    class Data;
+}
+
+namespace CSVRender
+{
+    class PreviewWidget : public SceneWidget
+    {
+            Q_OBJECT
+
+            const CSMWorld::Data& mData;
+            CSVRender::NavigationOrbit mOrbit;
+             NifOgre::ObjectScenePtr mObject;
+
+            void setup (const std::string& id);
+            ///< \param id ID of the referenceable to be viewed
+
+        public:
+
+            PreviewWidget (const CSMWorld::Data& data, const std::string& referenceableId,
+                QWidget *parent = 0);
+
+            PreviewWidget (const CSMWorld::Data& data, const std::string& referenceableId,
+                const std::string& referenceId, QWidget *parent = 0);
+
+        signals:
+
+            void closeRequest();
+    };
+}
+
+#endif
diff --git a/apps/opencs/view/world/previewsubview.cpp b/apps/opencs/view/world/previewsubview.cpp
new file mode 100644
index 000000000..0fa1d3b17
--- /dev/null
+++ b/apps/opencs/view/world/previewsubview.cpp
@@ -0,0 +1,50 @@
+
+#include "previewsubview.hpp"
+
+#include <QHBoxLayout>
+
+#include "../render/scenewidget.hpp"
+
+#include "scenetoolbar.hpp"
+
+#include "../render/previewwidget.hpp"
+
+CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
+: SubView (id)
+{
+    QHBoxLayout *layout = new QHBoxLayout;
+
+    layout->setContentsMargins (QMargins (0, 0, 0, 0));
+
+    if (document.getData().getReferenceables().searchId (id.getId())==-1)
+    {
+        std::string referenceableId =
+            document.getData().getReferences().getRecord (id.getId()).get().mRefID;
+
+        mScene =
+            new CSVRender::PreviewWidget (document.getData(), referenceableId, id.getId(), this);
+    }
+    else
+        mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), this);
+
+    SceneToolbar *toolbar = new SceneToolbar (48, this);
+
+    layout->addWidget (toolbar, 0);
+
+    layout->addWidget (mScene, 1);
+
+    QWidget *widget = new QWidget;
+
+    widget->setLayout (layout);
+
+    setWidget (widget);
+
+    connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
+}
+
+void CSVWorld::PreviewSubView::setEditLock (bool locked) {}
+
+void CSVWorld::PreviewSubView::closeRequest()
+{
+    deleteLater();
+}
\ No newline at end of file
diff --git a/apps/opencs/view/world/previewsubview.hpp b/apps/opencs/view/world/previewsubview.hpp
new file mode 100644
index 000000000..e7a2a261e
--- /dev/null
+++ b/apps/opencs/view/world/previewsubview.hpp
@@ -0,0 +1,36 @@
+#ifndef CSV_WORLD_PREVIEWSUBVIEW_H
+#define CSV_WORLD_PREVIEWSUBVIEW_H
+
+#include "../doc/subview.hpp"
+
+namespace CSMDoc
+{
+    class Document;
+}
+
+namespace CSVRender
+{
+    class PreviewWidget;
+}
+
+namespace CSVWorld
+{
+    class PreviewSubView : public CSVDoc::SubView
+    {
+            Q_OBJECT
+
+            CSVRender::PreviewWidget *mScene;
+
+        public:
+
+            PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
+
+            virtual void setEditLock (bool locked);
+
+        private slots:
+
+            void closeRequest();
+    };
+}
+
+#endif
diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp
index 74ce03cce..33a91330d 100644
--- a/apps/opencs/view/world/subviews.cpp
+++ b/apps/opencs/view/world/subviews.cpp
@@ -16,6 +16,7 @@
 #include "scenesubview.hpp"
 #include "dialoguecreator.hpp"
 #include "infocreator.hpp"
+#include "previewsubview.hpp"
 
 void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
 {
@@ -78,4 +79,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
         CreatorFactory<CSVFilter::FilterCreator> >);
 
     manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
+
+    manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory<PreviewSubView>);
 }
\ No newline at end of file