diff --git a/CMakeLists.txt b/CMakeLists.txt index 4efb19719..09b2b1621 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -273,6 +273,7 @@ endif(OGRE_STATIC) include_directories("." ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS} + ${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${PLATFORM_INCLUDE_DIR} diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 0d8e3d009..e2e5aa2e5 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -82,7 +82,7 @@ opencs_units (view/render opencs_units_noqt (view/render navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight - lightingbright object cell terrainstorage + lightingbright object cell terrainstorage textoverlay overlaymask overlaysystem ) opencs_hdrs_noqt (view/render @@ -199,6 +199,7 @@ endif(APPLE) target_link_libraries(opencs ${OGRE_LIBRARIES} + ${OGRE_Overlay_LIBRARIES} ${OGRE_STATIC_PLUGINS} ${SHINY_LIBRARIES} ${Boost_LIBRARIES} diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index fb185e426..982fc20d5 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -20,7 +20,8 @@ #include "model/world/data.hpp" CS::Editor::Editor (OgreInit::OgreInit& ogreInit) -: mUserSettings (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), +: mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr), + mViewManager (mDocumentManager), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) { std::pair > config = readConfig(); @@ -32,6 +33,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); + mOverlaySystem.reset (new CSVRender::OverlaySystem); + Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true, mFsStrict); @@ -65,6 +68,9 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) this, SLOT (createNewGame (const boost::filesystem::path&))); } +CS::Editor::~Editor () +{} + void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs) { for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) @@ -269,6 +275,9 @@ std::auto_ptr CS::Editor::setupGraphics() Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName(renderSystem)); + // Initialise Ogre::OverlaySystem after Ogre::Root but before initialisation + mOverlaySystem.get(); + Ogre::Root::getSingleton().initialise(false); // Create a hidden background window to keep resources @@ -295,6 +304,10 @@ std::auto_ptr CS::Editor::setupGraphics() sh::OgrePlatform* platform = new sh::OgrePlatform ("General", (mResources / "materials").string()); + // for font used in overlays + Ogre::Root::getSingleton().addResourceLocation ((mResources / "mygui").string(), + "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true); + if (!boost::filesystem::exists (mCfgMgr.getCachePath())) boost::filesystem::create_directories (mCfgMgr.getCachePath()); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index c87e24e77..cd39d53a4 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -27,6 +27,7 @@ #include "view/doc/newgame.hpp" #include "view/settings/dialog.hpp" +#include "view/render/overlaysystem.hpp" namespace OgreInit { @@ -42,6 +43,7 @@ namespace CS Nif::Cache mNifCache; Files::ConfigurationManager mCfgMgr; CSMSettings::UserSettings mUserSettings; + std::auto_ptr mOverlaySystem; CSMDoc::DocumentManager mDocumentManager; CSVDoc::ViewManager mViewManager; CSVDoc::StartupDialogue mStartup; @@ -64,6 +66,7 @@ namespace CS public: Editor (OgreInit::OgreInit& ogreInit); + ~Editor (); bool makeIPCServer(); void connectToIPCServer(); diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index a5e9d354a..93c1749c6 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -47,4 +47,9 @@ void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr& filter); + + protected: + + bool lessThan(const QModelIndex &left, const QModelIndex &right) const; }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 4fd66b14a..9ff24780c 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -214,3 +214,11 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int return addObjects (start, end); } + +float CSVRender::Cell::getTerrainHeightAt(const Ogre::Vector3 &pos) const +{ + if(mTerrain.get() != NULL) + return mTerrain->getHeightAt(pos); + else + return -std::numeric_limits::max(); +} diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index e63e09520..98056c354 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -70,6 +70,8 @@ namespace CSVRender /// \return Did this call result in a modification of the visual representation of /// this cell? bool referenceAdded (const QModelIndex& parent, int start, int end); + + float getTerrainHeightAt(const Ogre::Vector3 &pos) const; }; } diff --git a/apps/opencs/view/render/overlaymask.cpp b/apps/opencs/view/render/overlaymask.cpp new file mode 100644 index 000000000..09f020354 --- /dev/null +++ b/apps/opencs/view/render/overlaymask.cpp @@ -0,0 +1,52 @@ +#include "overlaymask.hpp" + +#include +#include + +#include "textoverlay.hpp" +#include "../../model/world/cellcoordinates.hpp" + +namespace CSVRender +{ + +// ideas from http://www.ogre3d.org/forums/viewtopic.php?f=5&t=44828#p486334 +OverlayMask::OverlayMask(std::map &overlays, Ogre::Viewport* viewport) + : mTextOverlays(overlays), mViewport(viewport) +{ +} + +OverlayMask::~OverlayMask() +{ +} + +void OverlayMask::setViewport(Ogre::Viewport *viewport) +{ + mViewport = viewport; +} + +void OverlayMask::preViewportUpdate(const Ogre::RenderTargetViewportEvent &event) +{ + if(event.source == mViewport) + { + Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton(); + for(Ogre::OverlayManager::OverlayMapIterator iter = overlayMgr.getOverlayIterator(); + iter.hasMoreElements();) + { + Ogre::Overlay* item = iter.getNext(); + for(Ogre::Overlay::Overlay2DElementsIterator it = item->get2DElementsIterator(); + it.hasMoreElements();) + { + Ogre::OverlayContainer* container = it.getNext(); + if(container) container->hide(); + } + } + + std::map::iterator it = mTextOverlays.begin(); + for(; it != mTextOverlays.end(); ++it) + { + it->second->show(true); + } + } +} + +} diff --git a/apps/opencs/view/render/overlaymask.hpp b/apps/opencs/view/render/overlaymask.hpp new file mode 100644 index 000000000..ec050cac4 --- /dev/null +++ b/apps/opencs/view/render/overlaymask.hpp @@ -0,0 +1,42 @@ +#ifndef OPENCS_VIEW_OVERLAYMASK_H +#define OPENCS_VIEW_OVERLAYMASK_H + +#include + +namespace Ogre +{ + class Viewport; + class RendertargetViewportEvent; +} + +namespace CSMWorld +{ + class CellCoordinates; +} + +namespace CSVRender +{ + class TextOverlay; + + class OverlayMask : public Ogre::RenderTargetListener + { + + std::map &mTextOverlays; + Ogre::Viewport* mViewport; + + public: + + OverlayMask(std::map &overlays, + Ogre::Viewport* viewport); + + virtual ~OverlayMask(); + + void setViewport(Ogre::Viewport *viewport); + + protected: + + virtual void preViewportUpdate(const Ogre::RenderTargetViewportEvent &event); + }; +} + +#endif // OPENCS_VIEW_OVERLAYMASK_H diff --git a/apps/opencs/view/render/overlaysystem.cpp b/apps/opencs/view/render/overlaysystem.cpp new file mode 100644 index 000000000..f565f5af0 --- /dev/null +++ b/apps/opencs/view/render/overlaysystem.cpp @@ -0,0 +1,34 @@ +#include "overlaysystem.hpp" + +#include + +#include + +namespace CSVRender +{ + OverlaySystem *OverlaySystem::mOverlaySystemInstance = 0; + + OverlaySystem::OverlaySystem() + { + assert(!mOverlaySystemInstance); + mOverlaySystemInstance = this; + mOverlaySystem = new Ogre::OverlaySystem(); + } + + OverlaySystem::~OverlaySystem() + { + delete mOverlaySystem; + } + + OverlaySystem &OverlaySystem::instance() + { + assert(mOverlaySystemInstance); + return *mOverlaySystemInstance; + } + + Ogre::OverlaySystem *OverlaySystem::get() + { + return mOverlaySystem; + } +} + diff --git a/apps/opencs/view/render/overlaysystem.hpp b/apps/opencs/view/render/overlaysystem.hpp new file mode 100644 index 000000000..f8a78f329 --- /dev/null +++ b/apps/opencs/view/render/overlaysystem.hpp @@ -0,0 +1,26 @@ +#ifndef OPENCS_VIEW_OVERLAYSYSTEM_H +#define OPENCS_VIEW_OVERLAYSYSTEM_H + +namespace Ogre +{ + class OverlaySystem; +} + +namespace CSVRender +{ + class OverlaySystem + { + Ogre::OverlaySystem *mOverlaySystem; + static OverlaySystem *mOverlaySystemInstance; + + public: + + OverlaySystem(); + ~OverlaySystem(); + static OverlaySystem &instance(); + + Ogre::OverlaySystem *get(); + }; +} + +#endif // OPENCS_VIEW_OVERLAYSYSTEM_H diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index aa74d4c91..8b143e93f 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -3,9 +3,19 @@ #include +#include + #include +#include +#include +#include +#include +#include +#include -#include +#include +#include "textoverlay.hpp" +#include "overlaymask.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/idtable.hpp" @@ -22,7 +32,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() const CSMWorld::IdCollection& cells = mDocument.getData().getCells(); { - // remove + // remove (or name/region modified) std::map::iterator iter (mCells.begin()); while (iter!=mCells.end()) @@ -32,12 +42,57 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() if (!mSelection.has (iter->first) || index==-1 || cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted) { + // delete overlays + std::map::iterator itOverlay = mTextOverlays.find(iter->first); + if(itOverlay != mTextOverlays.end()) + { + delete itOverlay->second; + mTextOverlays.erase(itOverlay); + } + + // destroy manual objects + getSceneManager()->destroyManualObject("manual"+iter->first.getId(mWorldspace)); + delete iter->second; mCells.erase (iter++); + modified = true; } else + { + // check if name or region field has changed + // FIXME: config setting + std::string name = cells.getRecord(index).get().mName; + std::string region = cells.getRecord(index).get().mRegion; + + std::map::iterator it = mTextOverlays.find(iter->first); + if(it != mTextOverlays.end()) + { + if(it->second->getDesc() != "") // previously had name + { + if(name != it->second->getDesc()) // new name + { + if(name != "") + it->second->setDesc(name); + else // name deleted, use region + it->second->setDesc(region); + it->second->update(); + } + } + else if(name != "") // name added + { + it->second->setDesc(name); + it->second->update(); + } + else if(region != it->second->getDesc()) // new region + { + it->second->setDesc(region); + it->second->update(); + } + modified = true; + } ++iter; + } } } @@ -53,15 +108,59 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted && mCells.find (*iter)==mCells.end()) { + Cell *cell = new Cell (mDocument.getData(), getSceneManager(), iter->getId (mWorldspace)); + mCells.insert (std::make_pair (*iter, cell)); + + float height = cell->getTerrainHeightAt(Ogre::Vector3( + ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2, + ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2, + 0)); if (setCamera) { setCamera = false; - getCamera()->setPosition (8192*iter->getX()+4096, 8192*iter->getY()+4096, 0); + getCamera()->setPosition ( + ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2, + ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2, + height); + // better camera position at the start + getCamera()->move(getCamera()->getDirection() * -6000); // FIXME: config setting } - mCells.insert (std::make_pair (*iter, - new Cell (mDocument.getData(), getSceneManager(), - iter->getId (mWorldspace)))); + Ogre::ManualObject* manual = + getSceneManager()->createManualObject("manual" + iter->getId(mWorldspace)); + manual->begin("BaseWhite", Ogre::RenderOperation::OT_LINE_LIST); + // define start and end point (x, y, z) + manual-> position(ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2, + ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2, + height); + manual-> position(ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2, + ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2, + height+200); // FIXME: config setting + manual->end(); + manual->setBoundingBox(Ogre::AxisAlignedBox( + ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2, + ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2, + height, + ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2, + ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2, + height+200)); + getSceneManager()->getRootSceneNode()->createChildSceneNode()->attachObject(manual); + manual->setVisible(false); + + CSVRender::TextOverlay *textDisp = + new CSVRender::TextOverlay(manual, getCamera(), iter->getId(mWorldspace)); + textDisp->enable(true); + textDisp->setCaption(iter->getId(mWorldspace)); + std::string desc = cells.getRecord(index).get().mName; + if(desc == "") desc = cells.getRecord(index).get().mRegion; + textDisp->setDesc(desc); // FIXME: config setting + textDisp->update(); + mTextOverlays.insert(std::make_pair(*iter, textDisp)); + if(!mOverlayMask) + { + mOverlayMask = new OverlayMask(mTextOverlays, getViewport()); + addRenderTargetListener(mOverlayMask); + } modified = true; } @@ -70,6 +169,53 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() return modified; } +void CSVRender::PagedWorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) +{ + if(event->button() == Qt::RightButton) + { + std::map::iterator iter = mTextOverlays.begin(); + for(; iter != mTextOverlays.end(); ++iter) + { + if(mDisplayCellCoord && + iter->second->isEnabled() && iter->second->container().contains(event->x(), event->y())) + { + std::cout << "clicked: " << iter->second->getCaption() << std::endl; + break; + } + } + } +} + +void CSVRender::PagedWorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) +{ + if(event->button() == Qt::RightButton) + { + std::cout << "double clicked" << std::endl; + } +} + +void CSVRender::PagedWorldspaceWidget::updateOverlay() +{ + if(getCamera()->getViewport()) + { + if((uint32_t)getCamera()->getViewport()->getVisibilityMask() + & (uint32_t)CSVRender::Element_CellMarker) + mDisplayCellCoord = true; + else + mDisplayCellCoord = false; + } + + if(!mTextOverlays.empty()) + { + std::map::iterator it = mTextOverlays.begin(); + for(; it != mTextOverlays.end(); ++it) + { + it->second->enable(mDisplayCellCoord); + it->second->update(); + } + } +} + void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) { @@ -149,7 +295,7 @@ std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction() CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document) : WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default"), - mControlElements(NULL) + mControlElements(NULL), mDisplayCellCoord(true), mOverlayMask(NULL) { QAbstractItemModel *cells = document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells); @@ -166,7 +312,20 @@ CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget() { for (std::map::iterator iter (mCells.begin()); iter!=mCells.end(); ++iter) + { + delete iter->second; + + getSceneManager()->destroyManualObject("manual"+iter->first.getId(mWorldspace)); + } + + for (std::map::iterator iter (mTextOverlays.begin()); + iter != mTextOverlays.end(); ++iter) + { delete iter->second; + } + + removeRenderTargetListener(mOverlayMask); + delete mOverlayMask; } void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint) diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index 249c0c5fb..17b6d10c5 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -10,6 +10,10 @@ namespace CSVRender { + + class TextOverlay; + class OverlayMask; + class PagedWorldspaceWidget : public WorldspaceWidget { Q_OBJECT @@ -19,6 +23,9 @@ namespace CSVRender std::map mCells; std::string mWorldspace; CSVWidget::SceneToolToggle *mControlElements; + bool mDisplayCellCoord; + std::map mTextOverlays; + OverlayMask *mOverlayMask; private: @@ -55,7 +62,7 @@ namespace CSVRender void useViewHint (const std::string& hint); - void setCellSelection (const CSMWorld::CellSelection& selection); + void setCellSelection(const CSMWorld::CellSelection& selection); /// \return Drop handled? virtual bool handleDrop (const std::vector& data, @@ -70,6 +77,14 @@ namespace CSVRender virtual unsigned int getElementMask() const; + protected: + + virtual void updateOverlay(); + + virtual void mouseReleaseEvent (QMouseEvent *event); + + virtual void mouseDoubleClickEvent (QMouseEvent *event); + signals: void cellSelectionChanged (const CSMWorld::CellSelection& selection); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 53599c3cb..3171e0496 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -11,12 +11,14 @@ #include #include #include +#include #include "../widget/scenetoolmode.hpp" #include "../../model/settings/usersettings.hpp" #include "navigation.hpp" #include "lighting.hpp" +#include "overlaysystem.hpp" namespace CSVRender { @@ -59,6 +61,9 @@ namespace CSVRender setLighting (&mLightingDay); + mOverlaySystem = OverlaySystem::instance().get(); + mSceneMgr->addRenderQueueListener(mOverlaySystem); + QTimer *timer = new QTimer (this); connect (timer, SIGNAL (timeout()), this, SLOT (update())); @@ -160,8 +165,12 @@ namespace CSVRender if (mWindow) Ogre::Root::getSingleton().destroyRenderTarget (mWindow); + if (mSceneMgr) + mSceneMgr->removeRenderQueueListener (mOverlaySystem); + if (mSceneMgr) Ogre::Root::getSingleton().destroySceneManager (mSceneMgr); + } void SceneWidget::setVisibilityMask (unsigned int mask) @@ -179,6 +188,24 @@ namespace CSVRender } } + void SceneWidget::addRenderTargetListener(Ogre::RenderTargetListener *listener) + { + mWindow->addListener(listener); + } + + void SceneWidget::removeRenderTargetListener(Ogre::RenderTargetListener *listener) + { + mWindow->removeListener(listener); + } + + Ogre::Viewport *SceneWidget::getViewport() + { + if (!mWindow) + updateOgreWindow(); + + return mViewport; + } + Ogre::SceneManager *SceneWidget::getSceneManager() { return mSceneMgr; @@ -379,9 +406,13 @@ namespace CSVRender { mUpdate = false; mWindow->update(); + updateOverlay(); } } + void SceneWidget::updateOverlay() + { } + void SceneWidget::setLighting (Lighting *lighting) { if (mLighting) diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 8301cd446..1adbf3f17 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -15,6 +15,8 @@ namespace Ogre class SceneManager; class RenderWindow; class Viewport; + class OverlaySystem; + class RenderTargetListener; } namespace CSVWidget @@ -50,6 +52,12 @@ namespace CSVRender void setNavigation (Navigation *navigation); ///< \attention The ownership of \a navigation is not transferred to *this. + void addRenderTargetListener(Ogre::RenderTargetListener *listener); + + void removeRenderTargetListener(Ogre::RenderTargetListener *listener); + + Ogre::Viewport *getViewport(); + Ogre::SceneManager *getSceneManager(); Ogre::Camera *getCamera(); @@ -59,6 +67,10 @@ namespace CSVRender void setDefaultAmbient (const Ogre::ColourValue& colour); ///< \note The actual ambient colour may differ based on lighting settings. + virtual void updateOverlay(); + + virtual void mouseReleaseEvent (QMouseEvent *event); + private: void paintEvent(QPaintEvent* e); void resizeEvent(QResizeEvent* e); @@ -76,17 +88,16 @@ namespace CSVRender void mouseMoveEvent (QMouseEvent *event); - void mouseReleaseEvent (QMouseEvent *event); - void updateOgreWindow(); void setLighting (Lighting *lighting); ///< \attention The ownership of \a lighting is not transferred to *this. - Ogre::Camera* mCamera; + Ogre::Camera* mCamera; Ogre::SceneManager* mSceneMgr; Ogre::RenderWindow* mWindow; Ogre::Viewport *mViewport; + Ogre::OverlaySystem *mOverlaySystem; Navigation *mNavigation; Lighting *mLighting; diff --git a/apps/opencs/view/render/textoverlay.cpp b/apps/opencs/view/render/textoverlay.cpp new file mode 100644 index 000000000..12831be9a --- /dev/null +++ b/apps/opencs/view/render/textoverlay.cpp @@ -0,0 +1,359 @@ +#include "textoverlay.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CSVRender +{ + +// Things to do: +// - configurable font size in pixels (automatically calulate everything else from it) +// - configurable texture to use +// - try material script +// - decide whether to use QPaint (http://www.ogre3d.org/tikiwiki/Ogre+overlays+using+Qt) + +// http://www.ogre3d.org/tikiwiki/ObjectTextDisplay +// http://www.ogre3d.org/tikiwiki/MovableTextOverlay +// http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures +// http://www.ogre3d.org/tikiwiki/ManualObject +TextOverlay::TextOverlay(const Ogre::MovableObject* obj, const Ogre::Camera* camera, const Ogre::String& id) + : mOverlay(0), mCaption(""), mDesc(""), mEnabled(true), mCamera(camera), mObj(obj), mId(id) + , mOnScreen(false) , mInstance(0), mFontHeight(16) // FIXME: make font height configurable +{ + if(id == "" || !camera || !obj) + throw std::runtime_error("TextOverlay could not be created."); + + // setup font + Ogre::FontManager &fontMgr = Ogre::FontManager::getSingleton(); + if (fontMgr.resourceExists("DejaVuLGC")) + mFont = fontMgr.getByName("DejaVuLGC","General"); + else + { + mFont = fontMgr.create("DejaVuLGC","General"); + mFont->setType(Ogre::FT_TRUETYPE); + mFont->setSource("DejaVuLGCSansMono.ttf"); + mFont->setTrueTypeSize(mFontHeight); + mFont->setTrueTypeResolution(96); + } + if(!mFont.isNull()) + mFont->load(); + else + throw std::runtime_error("TextOverlay font not loaded."); + + // setup overlay + Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton(); + mOverlay = overlayMgr.getByName("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance)); + // FIXME: this logic is badly broken as it is possible to delete an earlier instance + while(mOverlay != NULL) + { + mInstance++; + mOverlay = overlayMgr.getByName("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance)); + } + mOverlay = overlayMgr.create("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance)); + + // create texture + Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName("DynamicTransBlue"); + if(texture.isNull()) + { + texture = Ogre::TextureManager::getSingleton().createManual( + "DynamicTransBlue", // name + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, // type + 8, 8, // width & height + 0, // number of mipmaps + Ogre::PF_BYTE_BGRA, // pixel format + Ogre::TU_DEFAULT); // usage; should be TU_DYNAMIC_WRITE_ONLY_DISCARDABLE for + // textures updated very often (e.g. each frame) + + Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer(); + pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL); + const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock(); + + uint8_t* pDest = static_cast(pixelBox.data); + + // Fill in some pixel data. This will give a semi-transparent blue, + // but this is of course dependent on the chosen pixel format. + for (size_t j = 0; j < 8; j++) + { + for(size_t i = 0; i < 8; i++) + { + *pDest++ = 255; // B + *pDest++ = 0; // G + *pDest++ = 0; // R + *pDest++ = 63; // A + } + + pDest += pixelBox.getRowSkip() * Ogre::PixelUtil::getNumElemBytes(pixelBox.format); + } + pixelBuffer->unlock(); + } + + // setup material for containers + Ogre::MaterialPtr mQuadMaterial = Ogre::MaterialManager::getSingleton().getByName( + "TransOverlayMaterial"); + if(mQuadMaterial.isNull()) + { + Ogre::MaterialPtr mQuadMaterial = Ogre::MaterialManager::getSingleton().create( + "TransOverlayMaterial", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true ); + Ogre::Pass *pass = mQuadMaterial->getTechnique( 0 )->getPass( 0 ); + pass->setLightingEnabled( false ); + pass->setDepthWriteEnabled( false ); + pass->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA ); + + Ogre::TextureUnitState *tex = pass->createTextureUnitState("MyCustomState", 0); + tex->setTextureName("DynamicTransBlue"); + tex->setTextureFiltering( Ogre::TFO_ANISOTROPIC ); + mQuadMaterial->load(); + } + + mContainer = static_cast(overlayMgr.createOverlayElement( + "Panel", "container"+mId +"#"+Ogre::StringConverter::toString(mInstance))); + mContainer->setMaterialName("TransOverlayMaterial"); + mOverlay->add2D(mContainer); + + // setup text area overlay element + mElement = static_cast(overlayMgr.createOverlayElement( + "TextArea", "text"+mId +"#"+Ogre::StringConverter::toString(mInstance))); + mElement->setMetricsMode(Ogre::GMM_RELATIVE); + mElement->setDimensions(1.0, 1.0); + mElement->setMetricsMode(Ogre::GMM_PIXELS); + mElement->setPosition(2*fontHeight()/3, 1.3*fontHeight()/3); // 1.3 & 2 = fudge factor + + mElement->setFontName("DejaVuLGC"); + mElement->setCharHeight(fontHeight()); // NOTE: seems that this is required as well as font->setTrueTypeSize() + mElement->setHorizontalAlignment(Ogre::GHA_LEFT); + //mElement->setColour(Ogre::ColourValue(1.0, 1.0, 1.0)); // R, G, B + mElement->setColour(Ogre::ColourValue(1.0, 1.0, 0)); // yellow + + mContainer->addChild(mElement); + mOverlay->show(); +} + +void TextOverlay::getScreenCoordinates(const Ogre::Vector3& position, Ogre::Real& x, Ogre::Real& y) +{ + Ogre::Vector3 hcsPosition = mCamera->getProjectionMatrix() * (mCamera->getViewMatrix() * position); + + x = 1.0f - ((hcsPosition.x * 0.5f) + 0.5f); // 0 <= x <= 1 // left := 0,right := 1 + y = ((hcsPosition.y * 0.5f) + 0.5f); // 0 <= y <= 1 // bottom := 0,top := 1 +} + +void TextOverlay::getMinMaxEdgesOfAABBIn2D(float& MinX, float& MinY, float& MaxX, float& MaxY, + bool top) +{ + MinX = 0, MinY = 0, MaxX = 0, MaxY = 0; + float X[4]; // the 2D dots of the AABB in screencoordinates + float Y[4]; + + if(!mObj->isInScene()) + return; + + const Ogre::AxisAlignedBox &AABB = mObj->getWorldBoundingBox(true); // the AABB of the target + Ogre::Vector3 cornersOfAABB[4]; + if(top) + { + cornersOfAABB[0] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_TOP); + cornersOfAABB[1] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_TOP); + cornersOfAABB[2] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_TOP); + cornersOfAABB[3] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_TOP); + } + else + { + cornersOfAABB[0] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM); + cornersOfAABB[1] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM); + cornersOfAABB[2] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM); + cornersOfAABB[3] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_BOTTOM); + } + + //The normal vector of the plane. This points directly infront of the camera. + Ogre::Vector3 cameraPlainNormal = mCamera->getDerivedOrientation().zAxis(); + + //the plane that devides the space before and behind the camera. + Ogre::Plane CameraPlane = Ogre::Plane(cameraPlainNormal, mCamera->getDerivedPosition()); + + for (int i = 0; i < 4; i++) + { + X[i] = 0; + Y[i] = 0; + + getScreenCoordinates(cornersOfAABB[i],X[i],Y[i]); // transfor into 2d dots + + if (CameraPlane.getSide(cornersOfAABB[i]) == Ogre::Plane::NEGATIVE_SIDE) + { + if (i == 0) // accept the first set of values, no matter how bad it might be. + { + MinX = X[i]; + MinY = Y[i]; + MaxX = X[i]; + MaxY = Y[i]; + } + else // now compare if you get "better" values + { + if (MinX > X[i]) MinX = X[i]; + if (MinY > Y[i]) MinY = Y[i]; + if (MaxX < X[i]) MaxX = X[i]; + if (MaxY < Y[i]) MaxY = Y[i]; + } + } + else + { + MinX = 0; + MinY = 0; + MaxX = 0; + MaxY = 0; + break; + } + } +} + +TextOverlay::~TextOverlay() +{ + Ogre::OverlayManager::OverlayMapIterator iter = Ogre::OverlayManager::getSingleton().getOverlayIterator(); + if(!iter.hasMoreElements()) + mOverlay->hide(); + + Ogre::OverlayManager *overlayMgr = Ogre::OverlayManager::getSingletonPtr(); + mContainer->removeChild("text"+mId+"#"+Ogre::StringConverter::toString(mInstance)); + mOverlay->remove2D(mContainer); + + if(!iter.hasMoreElements()) + overlayMgr->destroy(mOverlay); +} + +void TextOverlay::show(bool show) +{ + if(show && mOnScreen) + mContainer->show(); + else + mContainer->hide(); +} + +void TextOverlay::enable(bool enable) +{ + if(enable == mOverlay->isVisible()) + return; + + mEnabled = enable; + if(enable) + mOverlay->show(); + else + mOverlay->hide(); +} + +bool TextOverlay::isEnabled() +{ + return mEnabled; +} + +void TextOverlay::setCaption(const Ogre::String& text) +{ + if(mCaption == text) + return; + + mCaption = text; + mElement->setCaption(text); +} + +void TextOverlay::setDesc(const Ogre::String& text) +{ + if(mDesc == text) + return; + + mDesc = text; + mElement->setCaption(mCaption + ((text == "") ? "" : ("\n" + text))); +} + +Ogre::FontPtr TextOverlay::getFont() +{ + return mFont; +} + +int TextOverlay::textWidth() +{ + float captionWidth = 0; + float descWidth = 0; + + for(Ogre::String::const_iterator i = mCaption.begin(); i < mCaption.end(); ++i) + { + if(*i == 0x0020) + captionWidth += getFont()->getGlyphAspectRatio(0x0030); + else + captionWidth += getFont()->getGlyphAspectRatio(*i); + } + + for(Ogre::String::const_iterator i = mDesc.begin(); i < mDesc.end(); ++i) + { + if(*i == 0x0020) + descWidth += getFont()->getGlyphAspectRatio(0x0030); + else + descWidth += getFont()->getGlyphAspectRatio(*i); + } + + captionWidth *= fontHeight(); + descWidth *= fontHeight(); + + return (int) std::max(captionWidth, descWidth); +} + +int TextOverlay::fontHeight() +{ + return mFontHeight; +} + +void TextOverlay::update() +{ + float min_x, max_x, min_y, max_y; + getMinMaxEdgesOfAABBIn2D(min_x, min_y, max_x, max_y, false); + + if ((min_x>0.0) && (max_x<1.0) && (min_y>0.0) && (max_y<1.0)) + { + mOnScreen = true; + mContainer->show(); + } + else + { + mOnScreen = false; + mContainer->hide(); + return; + } + + getMinMaxEdgesOfAABBIn2D(min_x, min_y, max_x, max_y); + + Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton(); + float viewportWidth = std::max(overlayMgr.getViewportWidth(), 1); // zero at the start + float viewportHeight = std::max(overlayMgr.getViewportHeight(), 1); // zero at the start + + int width = fontHeight()*2/3 + textWidth() + fontHeight()*2/3; // add margins + int height = fontHeight()/3 + fontHeight() + fontHeight()/3; + if(mDesc != "") + height = fontHeight()/3 + 2*fontHeight() + fontHeight()/3; + + float relTextWidth = width / viewportWidth; + float relTextHeight = height / viewportHeight; + + float posX = 1 - (min_x + max_x + relTextWidth)/2; + float posY = 1 - max_y - (relTextHeight-fontHeight()/3/viewportHeight); + + mContainer->setMetricsMode(Ogre::GMM_RELATIVE); + mContainer->setPosition(posX, posY); + mContainer->setDimensions(relTextWidth, relTextHeight); + + mPos = QRect(posX*viewportWidth, posY*viewportHeight, width, height); +} + +QRect TextOverlay::container() +{ + return mPos; +} + +} diff --git a/apps/opencs/view/render/textoverlay.hpp b/apps/opencs/view/render/textoverlay.hpp new file mode 100644 index 000000000..dbb347e56 --- /dev/null +++ b/apps/opencs/view/render/textoverlay.hpp @@ -0,0 +1,66 @@ +#ifndef OPENCS_VIEW_TEXTOVERLAY_H +#define OPENCS_VIEW_TEXTOVERLAY_H + +#include + +#include +#include + +namespace Ogre +{ + class MovableObject; + class Camera; + class Font; + class Overlay; + class OverlayContainer; + class TextAreaOverlayElement; +} + +namespace CSVRender +{ + + class TextOverlay + { + Ogre::Overlay* mOverlay; + Ogre::OverlayContainer* mContainer; + Ogre::TextAreaOverlayElement* mElement; + Ogre::String mCaption; + Ogre::String mDesc; + + const Ogre::MovableObject* mObj; + const Ogre::Camera* mCamera; + Ogre::FontPtr mFont; + int mFontHeight; // in pixels + Ogre::String mId; + QRect mPos; + + bool mEnabled; + bool mOnScreen; + int mInstance; + + Ogre::FontPtr getFont(); + int textWidth(); + int fontHeight(); + void getScreenCoordinates(const Ogre::Vector3& position, Ogre::Real& x, Ogre::Real& y); + void getMinMaxEdgesOfAABBIn2D(float& MinX, float& MinY, float& MaxX, float& MaxY, + bool top = true); + + public: + + TextOverlay(const Ogre::MovableObject* obj, const Ogre::Camera* camera, const Ogre::String &id); + virtual ~TextOverlay(); + + void enable(bool enable); // controlled from scene widget toolbar visibility mask + void show(bool show); // for updating from render target listener + bool isEnabled(); + void setCaption(const Ogre::String& text); + void setDesc(const Ogre::String& text); + void update(); + QRect container(); // for detection of mouse click on the overlay + Ogre::String getCaption() { return mCaption; } // FIXME: debug + Ogre::String getDesc() { return mDesc; } + }; + +} + +#endif // OPENCS_VIEW_TEXTOVERLAY_H diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 75ea4f46e..ebb15ea2c 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -313,4 +313,9 @@ void CSVRender::WorldspaceWidget::elementSelectionChanged() { setVisibilityMask (getElementMask()); flagAsModified(); + updateOverlay(); +} + +void CSVRender::WorldspaceWidget::updateOverlay() +{ } diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 0754e9ecf..4830d772b 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -88,6 +88,8 @@ namespace CSVRender CSMDoc::Document& getDocument(); + virtual void updateOverlay(); + private: void dragEnterEvent(QDragEnterEvent *event); @@ -134,4 +136,4 @@ namespace CSVRender }; } -#endif \ No newline at end of file +#endif diff --git a/cmake/FindOGRE.cmake b/cmake/FindOGRE.cmake index 5608c528c..51589698f 100644 --- a/cmake/FindOGRE.cmake +++ b/cmake/FindOGRE.cmake @@ -18,7 +18,7 @@ # Once done, this will define # # OGRE_FOUND - system has OGRE -# OGRE_INCLUDE_DIRS - the OGRE include directories +# OGRE_INCLUDE_DIRS - the OGRE include directories # OGRE_LIBRARIES - link these to use the OGRE core # OGRE_BINARY_REL - location of the main Ogre binary (win32 non-static only, release) # OGRE_BINARY_DBG - location of the main Ogre binaries (win32 non-static only, debug) @@ -35,7 +35,7 @@ # # OGRE_${COMPONENT}_FOUND - ${COMPONENT} is available # OGRE_${COMPONENT}_INCLUDE_DIRS - additional include directories for ${COMPONENT} -# OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT} +# OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT} # OGRE_${COMPONENT}_BINARY_REL - location of the component binary (win32 non-static only, release) # OGRE_${COMPONENT}_BINARY_DBG - location of the component binary (win32 non-static only, debug) # @@ -110,9 +110,9 @@ if (OGRE_PREFIX_SOURCE AND OGRE_PREFIX_BUILD) set(OGRE_INC_SEARCH_PATH ${dir}/include ${OGRE_INC_SEARCH_PATH}) set(OGRE_LIB_SEARCH_PATH ${dir}/lib ${OGRE_LIB_SEARCH_PATH}) set(OGRE_BIN_SEARCH_PATH ${dir}/bin ${OGRE_BIN_SEARCH_PATH}) - set(OGRE_BIN_SEARCH_PATH ${dir}/Samples/Common/bin ${OGRE_BIN_SEARCH_PATH}) + set(OGRE_BIN_SEARCH_PATH ${dir}/Samples/Common/bin ${OGRE_BIN_SEARCH_PATH}) endforeach(dir) - + if (OGRE_PREFIX_DEPENDENCIES_DIR) set(OGRE_INC_SEARCH_PATH ${OGRE_PREFIX_DEPENDENCIES_DIR}/include ${OGRE_INC_SEARCH_PATH}) set(OGRE_LIB_SEARCH_PATH ${OGRE_PREFIX_DEPENDENCIES_DIR}/lib ${OGRE_LIB_SEARCH_PATH}) @@ -124,12 +124,12 @@ else() endif () # redo search if any of the environmental hints changed -set(OGRE_COMPONENTS Paging Terrain +set(OGRE_COMPONENTS Paging Terrain Overlay Plugin_BSPSceneManager Plugin_CgProgramManager Plugin_OctreeSceneManager Plugin_OctreeZone Plugin_PCZSceneManager Plugin_ParticleFX RenderSystem_Direct3D10 RenderSystem_Direct3D9 RenderSystem_GL RenderSystem_GLES2) -set(OGRE_RESET_VARS - OGRE_CONFIG_INCLUDE_DIR OGRE_INCLUDE_DIR +set(OGRE_RESET_VARS + OGRE_CONFIG_INCLUDE_DIR OGRE_INCLUDE_DIR OGRE_LIBRARY_FWK OGRE_LIBRARY_REL OGRE_LIBRARY_DBG OGRE_PLUGIN_DIR_DBG OGRE_PLUGIN_DIR_REL OGRE_MEDIA_DIR) foreach (comp ${OGRE_COMPONENTS}) @@ -148,7 +148,7 @@ if(NOT OGRE_BUILD_PLATFORM_IPHONE AND APPLE) # try to find framework on OSX findpkg_framework(OGRE) else() - set(OGRE_LIBRARY_FWK "") + set(OGRE_LIBRARY_FWK "") endif() # locate Ogre include files @@ -215,8 +215,8 @@ list(REMOVE_DUPLICATES OGRE_INCLUDE_DIR) findpkg_finish(OGRE) add_parent_dir(OGRE_INCLUDE_DIRS OGRE_INCLUDE_DIR) if (OGRE_SOURCE) - # If working from source rather than SDK, add samples include - set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} "${OGRE_SOURCE}/Samples/Common/include") + # If working from source rather than SDK, add samples include + set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} "${OGRE_SOURCE}/Samples/Common/include") endif() mark_as_advanced(OGRE_CONFIG_INCLUDE_DIR OGRE_MEDIA_DIR OGRE_PLUGIN_DIR_REL OGRE_PLUGIN_DIR_DBG) @@ -259,13 +259,13 @@ if (OGRE_STATIC) endif () if (ANDROID) - set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${OGRE_LIBRARY_FWK} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES} - ${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES} + set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${OGRE_LIBRARY_FWK} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES} + ${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES} ${Cocoa_LIBRARIES} ${Carbon_LIBRARIES}) else () - set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${OGRE_LIBRARY_FWK} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES} - ${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES} - ${X11_LIBRARIES} ${X11_Xt_LIBRARIES} ${XAW_LIBRARY} ${X11_Xrandr_LIB} + set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${OGRE_LIBRARY_FWK} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES} + ${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES} + ${X11_LIBRARIES} ${X11_Xt_LIBRARIES} ${XAW_LIBRARY} ${X11_Xrandr_LIB} ${Cocoa_LIBRARIES} ${Carbon_LIBRARIES}) endif() @@ -279,9 +279,9 @@ endif() set(OGRE_DEPS_FOUND FALSE) endif () if (UNIX AND NOT APPLE AND NOT ANDROID) - if (NOT X11_FOUND) + if (NOT X11_FOUND) set(OGRE_DEPS_FOUND FALSE) - endif () + endif () endif () if (OGRE_CONFIG_THREADS) @@ -311,7 +311,7 @@ endif() endif () endif () endif () - + if (NOT OGRE_DEPS_FOUND) pkg_message(OGRE "Could not find all required dependencies for the Ogre package.") set(OGRE_FOUND FALSE) @@ -329,13 +329,13 @@ set(OGRE_LIBRARY_DIRS ${OGRE_LIBRARY_DIR_REL} ${OGRE_LIBRARY_DIR_DBG}) # find binaries if (NOT OGRE_STATIC) - if (WIN32) - find_file(OGRE_BINARY_REL NAMES "OgreMain.dll" HINTS ${OGRE_BIN_SEARCH_PATH} + if (WIN32) + find_file(OGRE_BINARY_REL NAMES "OgreMain.dll" HINTS ${OGRE_BIN_SEARCH_PATH} PATH_SUFFIXES "" release relwithdebinfo minsizerel) - find_file(OGRE_BINARY_DBG NAMES "OgreMain_d.dll" HINTS ${OGRE_BIN_SEARCH_PATH} + find_file(OGRE_BINARY_DBG NAMES "OgreMain_d.dll" HINTS ${OGRE_BIN_SEARCH_PATH} PATH_SUFFIXES "" debug ) - endif() - mark_as_advanced(OGRE_BINARY_REL OGRE_BINARY_DBG) + endif() + mark_as_advanced(OGRE_BINARY_REL OGRE_BINARY_DBG) endif() @@ -343,7 +343,7 @@ endif() # Find Ogre components ######################################################### -set(OGRE_COMPONENT_SEARCH_PATH_REL +set(OGRE_COMPONENT_SEARCH_PATH_REL ${OGRE_LIBRARY_DIR_REL}/.. ${OGRE_LIBRARY_DIR_REL}/../.. ${OGRE_BIN_SEARCH_PATH} @@ -356,7 +356,7 @@ set(OGRE_COMPONENT_SEARCH_PATH_DBG macro(ogre_find_component COMPONENT HEADER) findpkg_begin(OGRE_${COMPONENT}) - find_path(OGRE_${COMPONENT}_INCLUDE_DIR NAMES ${HEADER} HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} PATH_SUFFIXES ${COMPONENT} OGRE/${COMPONENT} Components/${COMPONENT}/include) + find_path(OGRE_${COMPONENT}_INCLUDE_DIR NAMES ${HEADER} HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_INCLUDE_DIR}/OGRE/${COMPONENT} ${OGRE_PREFIX_SOURCE} PATH_SUFFIXES ${COMPONENT} OGRE/${COMPONENT} Components/${COMPONENT}/include) set(OGRE_${COMPONENT}_LIBRARY_NAMES "Ogre${COMPONENT}${OGRE_LIB_SUFFIX}") get_debug_names(OGRE_${COMPONENT}_LIBRARY_NAMES) find_library(OGRE_${COMPONENT}_LIBRARY_REL NAMES ${OGRE_${COMPONENT}_LIBRARY_NAMES} HINTS ${OGRE_LIBRARY_DIR_REL} PATH_SUFFIXES "" "release" "relwithdebinfo" "minsizerel") @@ -364,19 +364,25 @@ macro(ogre_find_component COMPONENT HEADER) make_library_set(OGRE_${COMPONENT}_LIBRARY) findpkg_finish(OGRE_${COMPONENT}) if (OGRE_${COMPONENT}_FOUND) + if (APPLE) + include_directories("${OGRE_INCLUDE_DIR}/OGRE/${COMPONENT}") + endif() # find binaries if (NOT OGRE_STATIC) - if (WIN32) - find_file(OGRE_${COMPONENT}_BINARY_REL NAMES "Ogre${COMPONENT}.dll" HINTS ${OGRE_COMPONENT_SEARCH_PATH_REL} PATH_SUFFIXES "" bin bin/release bin/relwithdebinfo bin/minsizerel release) - find_file(OGRE_${COMPONENT}_BINARY_DBG NAMES "Ogre${COMPONENT}_d.dll" HINTS ${OGRE_COMPONENT_SEARCH_PATH_DBG} PATH_SUFFIXES "" bin bin/debug debug) - endif() - mark_as_advanced(OGRE_${COMPONENT}_BINARY_REL OGRE_${COMPONENT}_BINARY_DBG) + if (WIN32) + find_file(OGRE_${COMPONENT}_BINARY_REL NAMES "Ogre${COMPONENT}.dll" HINTS ${OGRE_COMPONENT_SEARCH_PATH_REL} PATH_SUFFIXES "" bin bin/release bin/relwithdebinfo bin/minsizerel release) + find_file(OGRE_${COMPONENT}_BINARY_DBG NAMES "Ogre${COMPONENT}_d.dll" HINTS ${OGRE_COMPONENT_SEARCH_PATH_DBG} PATH_SUFFIXES "" bin bin/debug debug) + endif() + mark_as_advanced(OGRE_${COMPONENT}_BINARY_REL OGRE_${COMPONENT}_BINARY_DBG) endif() endif() endmacro() # look for Paging component ogre_find_component(Paging OgrePaging.h) +# look for Overlay component +ogre_find_component(Overlay OgreOverlaySystem.h) +ogre_find_component(Overlay OgreOverlay.h) # look for Terrain component ogre_find_component(Terrain OgreTerrain.h) # look for Property component @@ -395,17 +401,17 @@ macro(ogre_find_plugin PLUGIN HEADER) set(TMP_CMAKE_LIB_PREFIX ${CMAKE_FIND_LIBRARY_PREFIXES}) set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "") endif() - + # strip RenderSystem_ or Plugin_ prefix from plugin name string(REPLACE "RenderSystem_" "" PLUGIN_TEMP ${PLUGIN}) string(REPLACE "Plugin_" "" PLUGIN_NAME ${PLUGIN_TEMP}) - + # header files for plugins are not usually needed, but find them anyway if they are present set(OGRE_PLUGIN_PATH_SUFFIXES - PlugIns PlugIns/${PLUGIN_NAME} Plugins Plugins/${PLUGIN_NAME} ${PLUGIN} + PlugIns PlugIns/${PLUGIN_NAME} Plugins Plugins/${PLUGIN_NAME} ${PLUGIN} RenderSystems RenderSystems/${PLUGIN_NAME} ${ARGN}) - find_path(OGRE_${PLUGIN}_INCLUDE_DIR NAMES ${HEADER} - HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} + find_path(OGRE_${PLUGIN}_INCLUDE_DIR NAMES ${HEADER} + HINTS ${OGRE_INCLUDE_DIRS} ${OGRE_PREFIX_SOURCE} PATH_SUFFIXES ${OGRE_PLUGIN_PATH_SUFFIXES}) # find link libraries for plugins set(OGRE_${PLUGIN}_LIBRARY_NAMES "${PLUGIN}${OGRE_LIB_SUFFIX}") @@ -443,15 +449,15 @@ macro(ogre_find_plugin PLUGIN HEADER) if (OGRE_${PLUGIN}_FOUND) if (NOT OGRE_PLUGIN_DIR_REL OR NOT OGRE_PLUGIN_DIR_DBG) if (WIN32) - set(OGRE_PLUGIN_SEARCH_PATH_REL + set(OGRE_PLUGIN_SEARCH_PATH_REL ${OGRE_LIBRARY_DIR_REL}/.. ${OGRE_LIBRARY_DIR_REL}/../.. - ${OGRE_BIN_SEARCH_PATH} + ${OGRE_BIN_SEARCH_PATH} ) set(OGRE_PLUGIN_SEARCH_PATH_DBG ${OGRE_LIBRARY_DIR_DBG}/.. ${OGRE_LIBRARY_DIR_DBG}/../.. - ${OGRE_BIN_SEARCH_PATH} + ${OGRE_BIN_SEARCH_PATH} ) find_path(OGRE_PLUGIN_DIR_REL NAMES "${PLUGIN}.dll" HINTS ${OGRE_PLUGIN_SEARCH_PATH_REL} PATH_SUFFIXES "" bin bin/release bin/relwithdebinfo bin/minsizerel release) @@ -468,16 +474,16 @@ macro(ogre_find_plugin PLUGIN HEADER) set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP}) endif () endif () - - # find binaries - if (NOT OGRE_STATIC) - if (WIN32) - find_file(OGRE_${PLUGIN}_REL NAMES "${PLUGIN}.dll" HINTS ${OGRE_PLUGIN_DIR_REL}) - find_file(OGRE_${PLUGIN}_DBG NAMES "${PLUGIN}_d.dll" HINTS ${OGRE_PLUGIN_DIR_DBG}) - endif() - mark_as_advanced(OGRE_${PLUGIN}_REL OGRE_${PLUGIN}_DBG) - endif() - + + # find binaries + if (NOT OGRE_STATIC) + if (WIN32) + find_file(OGRE_${PLUGIN}_REL NAMES "${PLUGIN}.dll" HINTS ${OGRE_PLUGIN_DIR_REL}) + find_file(OGRE_${PLUGIN}_DBG NAMES "${PLUGIN}_d.dll" HINTS ${OGRE_PLUGIN_DIR_DBG}) + endif() + mark_as_advanced(OGRE_${PLUGIN}_REL OGRE_${PLUGIN}_DBG) + endif() + endif () if (TMP_CMAKE_LIB_PREFIX) @@ -521,7 +527,7 @@ if (OGRE_STATIC) if (NOT Cg_FOUND) set(OGRE_Plugin_CgProgramManager_FOUND FALSE) endif () - + set(OGRE_RenderSystem_Direct3D9_LIBRARIES ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${DirectX9_LIBRARIES} ) diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 6574f096b..4f656f9c4 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -45,7 +45,7 @@ static char strict_normalize_char(char ch) static char nonstrict_normalize_char(char ch) { - return ch == '\\' ? '/' : std::tolower(ch); + return ch == '\\' ? '/' : std::tolower(ch,std::locale::classic()); } template