mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-26 14:56:39 +00:00 
			
		
		
		
	Merge branch 'next' into terrain
Conflicts: apps/openmw/CMakeLists.txt apps/openmw/mwrender/renderingmanager.cpp
This commit is contained in:
		
						commit
						f2a7acb102
					
				
					 21 changed files with 963 additions and 26 deletions
				
			
		|  | @ -14,7 +14,8 @@ set(GAME_HEADER | ||||||
| source_group(game FILES ${GAME} ${GAME_HEADER}) | source_group(game FILES ${GAME} ${GAME_HEADER}) | ||||||
| 
 | 
 | ||||||
| add_openmw_dir (mwrender | add_openmw_dir (mwrender | ||||||
|     renderingmanager debugging sky terrain terrainmaterial player animation npcanimation creatureanimation actors objects renderinginterface |     renderingmanager debugging sky player animation npcanimation creatureanimation actors objects | ||||||
|  |     renderinginterface localmap terrain terrainmaterial | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| add_openmw_dir (mwinput | add_openmw_dir (mwinput | ||||||
|  |  | ||||||
|  | @ -61,6 +61,8 @@ HUD::HUD(int width, int height, int fpsLevel) | ||||||
|     setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds"); |     setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds"); | ||||||
|     setSpellStatus(65, 100); |     setSpellStatus(65, 100); | ||||||
|     setEffect("icons\\s\\tx_s_chameleon.dds"); |     setEffect("icons\\s\\tx_s_chameleon.dds"); | ||||||
|  | 
 | ||||||
|  |     LocalMapBase::init(minimap, this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void HUD::setFPS(float fps) | void HUD::setFPS(float fps) | ||||||
|  | @ -142,3 +144,161 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& v | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void HUD::setPlayerDir(const float x, const float y) | ||||||
|  | { | ||||||
|  |     MyGUI::ISubWidget* main = compass->getSubWidgetMain(); | ||||||
|  |     MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>(); | ||||||
|  |     rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); | ||||||
|  |     float angle = std::atan2(x,y); | ||||||
|  |     rotatingSubskin->setAngle(angle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HUD::setPlayerPos(const float x, const float y) | ||||||
|  | { | ||||||
|  |     MyGUI::IntSize size = minimap->getCanvasSize(); | ||||||
|  |     MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); | ||||||
|  |     MyGUI::IntCoord viewsize = minimap->getCoord(); | ||||||
|  |     MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); | ||||||
|  | 
 | ||||||
|  |     minimap->setViewOffset(pos); | ||||||
|  |     compass->setPosition(MyGUI::IntPoint(x*512-16, y*512-16)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MapWindow::MapWindow() | ||||||
|  |   : Layout("openmw_map_window_layout.xml"), mGlobal(false) | ||||||
|  | { | ||||||
|  |     setCoord(500,0,320,300); | ||||||
|  |     setText("WorldButton", "World"); | ||||||
|  |     setImage("Compass", "textures\\compass.dds"); | ||||||
|  | 
 | ||||||
|  |     // Obviously you should override this later on
 | ||||||
|  |     setCellName("No Cell Loaded"); | ||||||
|  | 
 | ||||||
|  |     getWidget(mLocalMap, "LocalMap"); | ||||||
|  |     getWidget(mGlobalMap, "GlobalMap"); | ||||||
|  |     getWidget(mPlayerArrow, "Compass"); | ||||||
|  | 
 | ||||||
|  |     getWidget(mButton, "WorldButton"); | ||||||
|  |     mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); | ||||||
|  | 
 | ||||||
|  |     MyGUI::Button* eventbox; | ||||||
|  |     getWidget(eventbox, "EventBox"); | ||||||
|  |     eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); | ||||||
|  |     eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); | ||||||
|  | 
 | ||||||
|  |     LocalMapBase::init(mLocalMap, this); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWindow::setVisible(bool b) | ||||||
|  | { | ||||||
|  |     mMainWidget->setVisible(b); | ||||||
|  |     if (b) | ||||||
|  |         mVisible = true; | ||||||
|  |     else | ||||||
|  |         mVisible = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWindow::setCellName(const std::string& cellName) | ||||||
|  | { | ||||||
|  |     static_cast<MyGUI::Window*>(mMainWidget)->setCaption(cellName); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWindow::setPlayerPos(const float x, const float y) | ||||||
|  | { | ||||||
|  |     if (mGlobal || mVisible) return; | ||||||
|  |     MyGUI::IntSize size = mLocalMap->getCanvasSize(); | ||||||
|  |     MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); | ||||||
|  |     MyGUI::IntCoord viewsize = mLocalMap->getCoord(); | ||||||
|  |     MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); | ||||||
|  |     mLocalMap->setViewOffset(pos); | ||||||
|  | 
 | ||||||
|  |     mPlayerArrow->setPosition(MyGUI::IntPoint(x*512-16, y*512-16)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWindow::setPlayerDir(const float x, const float y) | ||||||
|  | { | ||||||
|  |     if (!mVisible) return; | ||||||
|  |     MyGUI::ISubWidget* main = mPlayerArrow->getSubWidgetMain(); | ||||||
|  |     MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>(); | ||||||
|  |     rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); | ||||||
|  |     float angle = std::atan2(x,y); | ||||||
|  |     rotatingSubskin->setAngle(angle); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) | ||||||
|  | { | ||||||
|  |     if (_id!=MyGUI::MouseButton::Left) return; | ||||||
|  |     if (!mGlobal) | ||||||
|  |         mLastDragPos = MyGUI::IntPoint(_left, _top); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) | ||||||
|  | { | ||||||
|  |     if (_id!=MyGUI::MouseButton::Left) return; | ||||||
|  | 
 | ||||||
|  |     if (!mGlobal) | ||||||
|  |     { | ||||||
|  |         MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos; | ||||||
|  |         mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff ); | ||||||
|  | 
 | ||||||
|  |         mLastDragPos = MyGUI::IntPoint(_left, _top); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) | ||||||
|  | { | ||||||
|  |     mGlobal = !mGlobal; | ||||||
|  |     mGlobalMap->setVisible(mGlobal); | ||||||
|  |     mLocalMap->setVisible(!mGlobal); | ||||||
|  | 
 | ||||||
|  |     mButton->setCaption( mGlobal ? "Local" : "World" ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout) | ||||||
|  | { | ||||||
|  |     mLocalMap = widget; | ||||||
|  |     mLayout = layout; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMapBase::setCellPrefix(const std::string& prefix) | ||||||
|  | { | ||||||
|  |     mPrefix = prefix; | ||||||
|  |     mChanged = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMapBase::setActiveCell(const int x, const int y, bool interior) | ||||||
|  | { | ||||||
|  |     if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
 | ||||||
|  |     for (int mx=0; mx<3; ++mx) | ||||||
|  |     { | ||||||
|  |         for (int my=0; my<3; ++my) | ||||||
|  |         { | ||||||
|  |             std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_" | ||||||
|  |                     + boost::lexical_cast<std::string>(my); | ||||||
|  | 
 | ||||||
|  |             std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(x + (mx-1)) + "_" | ||||||
|  |                     + boost::lexical_cast<std::string>(y + (interior ? (my-1) : -1*(my-1))); | ||||||
|  | 
 | ||||||
|  |             MyGUI::ImageBox* box; | ||||||
|  |             mLayout->getWidget(box, name); | ||||||
|  |             MyGUI::ImageBox* fog; | ||||||
|  |             mLayout->getWidget(fog, name+"_fog"); | ||||||
|  | 
 | ||||||
|  |             if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) | ||||||
|  |                 box->setImageTexture(image); | ||||||
|  |             else | ||||||
|  |                 box->setImageTexture("black.png"); | ||||||
|  | 
 | ||||||
|  |             if (MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) | ||||||
|  |                 fog->setImageTexture(image+"_fog"); | ||||||
|  |             else | ||||||
|  |                 fog->setImageTexture("black.png"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     mInterior = interior; | ||||||
|  |     mCurX = x; | ||||||
|  |     mCurY = y; | ||||||
|  |     mChanged = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -14,6 +14,8 @@ | ||||||
| #include "../mwmechanics/stat.hpp" | #include "../mwmechanics/stat.hpp" | ||||||
| #include "window_base.hpp" | #include "window_base.hpp" | ||||||
| 
 | 
 | ||||||
|  | #include <cmath> | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|   This file contains classes corresponding to window layouts |   This file contains classes corresponding to window layouts | ||||||
|   defined in resources/mygui/ *.xml. |   defined in resources/mygui/ *.xml. | ||||||
|  | @ -29,7 +31,25 @@ | ||||||
| 
 | 
 | ||||||
| namespace MWGui | namespace MWGui | ||||||
| { | { | ||||||
|   class HUD : public OEngine::GUI::Layout |   class LocalMapBase | ||||||
|  |   { | ||||||
|  |   public: | ||||||
|  |     void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout); | ||||||
|  | 
 | ||||||
|  |     void setCellPrefix(const std::string& prefix); | ||||||
|  |     void setActiveCell(const int x, const int y, bool interior=false); | ||||||
|  | 
 | ||||||
|  |   protected: | ||||||
|  |     int mCurX, mCurY; | ||||||
|  |     bool mInterior; | ||||||
|  |     MyGUI::ScrollView* mLocalMap; | ||||||
|  |     std::string mPrefix; | ||||||
|  |     bool mChanged; | ||||||
|  | 
 | ||||||
|  |     OEngine::GUI::Layout* mLayout; | ||||||
|  |   }; | ||||||
|  |    | ||||||
|  |   class HUD : public OEngine::GUI::Layout, public LocalMapBase | ||||||
|   { |   { | ||||||
|   public: |   public: | ||||||
|     HUD(int width, int height, int fpsLevel); |     HUD(int width, int height, int fpsLevel); | ||||||
|  | @ -43,13 +63,15 @@ namespace MWGui | ||||||
|     void setFPS(float fps); |     void setFPS(float fps); | ||||||
|     void setTriangleCount(size_t count); |     void setTriangleCount(size_t count); | ||||||
|     void setBatchCount(size_t count); |     void setBatchCount(size_t count); | ||||||
|  |     void setPlayerDir(const float x, const float y); | ||||||
|  |     void setPlayerPos(const float x, const float y); | ||||||
| 
 | 
 | ||||||
|     MyGUI::ProgressPtr health, magicka, stamina; |     MyGUI::ProgressPtr health, magicka, stamina; | ||||||
|     MyGUI::ImageBox *weapImage, *spellImage; |     MyGUI::ImageBox *weapImage, *spellImage; | ||||||
|     MyGUI::ProgressPtr weapStatus, spellStatus; |     MyGUI::ProgressPtr weapStatus, spellStatus; | ||||||
|     MyGUI::WidgetPtr effectBox; |     MyGUI::WidgetPtr effectBox; | ||||||
|     MyGUI::ImageBox* effect1; |     MyGUI::ImageBox* effect1; | ||||||
|     MyGUI::ImageBox* minimap; |     MyGUI::ScrollView* minimap; | ||||||
|     MyGUI::ImageBox* compass; |     MyGUI::ImageBox* compass; | ||||||
|     MyGUI::ImageBox* crosshair; |     MyGUI::ImageBox* crosshair; | ||||||
| 
 | 
 | ||||||
|  | @ -59,24 +81,27 @@ namespace MWGui | ||||||
|     MyGUI::TextBox* batchcounter; |     MyGUI::TextBox* batchcounter; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   class MapWindow : public OEngine::GUI::Layout |   class MapWindow : public OEngine::GUI::Layout, public LocalMapBase | ||||||
|   { |   { | ||||||
|   public: |   public: | ||||||
|     MapWindow() |     MapWindow(); | ||||||
|       : Layout("openmw_map_window_layout.xml") |  | ||||||
|     { |  | ||||||
|       setCoord(500,0,320,300); |  | ||||||
|       setText("WorldButton", "World"); |  | ||||||
|       setImage("Compass", "compass.dds"); |  | ||||||
| 
 | 
 | ||||||
|       // Obviously you should override this later on
 |     void setVisible(bool b); | ||||||
|       setCellName("No Cell Loaded"); |     void setPlayerPos(const float x, const float y); | ||||||
|     } |     void setPlayerDir(const float x, const float y); | ||||||
|  |     void setCellName(const std::string& cellName); | ||||||
|    |    | ||||||
|     void setCellName(const std::string& cellName) |   private: | ||||||
|     { |     void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); | ||||||
|       static_cast<MyGUI::Window*>(mMainWidget)->setCaption(cellName); |     void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); | ||||||
|     } |     void onWorldButtonClicked(MyGUI::Widget* _sender); | ||||||
|  | 
 | ||||||
|  |     MyGUI::ScrollView* mGlobalMap; | ||||||
|  |     MyGUI::ImageBox* mPlayerArrow; | ||||||
|  |     MyGUI::Button* mButton; | ||||||
|  |     MyGUI::IntPoint mLastDragPos; | ||||||
|  |     bool mVisible; | ||||||
|  |     bool mGlobal; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   class MainMenu : public OEngine::GUI::Layout |   class MainMenu : public OEngine::GUI::Layout | ||||||
|  |  | ||||||
|  | @ -400,3 +400,47 @@ const ESMS::ESMStore& WindowManager::getStore() const | ||||||
| { | { | ||||||
|     return environment.mWorld->getStore(); |     return environment.mWorld->getStore(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) | ||||||
|  | { | ||||||
|  |     if (!(cell->cell->data.flags & ESM::Cell::Interior)) | ||||||
|  |     { | ||||||
|  |         std::string name; | ||||||
|  |         if (cell->cell->name != "") | ||||||
|  |             name = cell->cell->name; | ||||||
|  |         else | ||||||
|  |             name = cell->cell->region; | ||||||
|  | 
 | ||||||
|  |         map->setCellName( name ); | ||||||
|  | 
 | ||||||
|  |         map->setCellPrefix("Cell"); | ||||||
|  |         hud->setCellPrefix("Cell"); | ||||||
|  |         map->setActiveCell( cell->cell->data.gridX, cell->cell->data.gridY ); | ||||||
|  |         hud->setActiveCell( cell->cell->data.gridX, cell->cell->data.gridY ); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         map->setCellName( cell->cell->name ); | ||||||
|  |         map->setCellPrefix( cell->cell->name ); | ||||||
|  |         hud->setCellPrefix( cell->cell->name ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void WindowManager::setInteriorMapTexture(const int x, const int y) | ||||||
|  | { | ||||||
|  |     map->setActiveCell(x,y, true); | ||||||
|  |     hud->setActiveCell(x,y, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void WindowManager::setPlayerPos(const float x, const float y) | ||||||
|  | { | ||||||
|  |     map->setPlayerPos(x,y); | ||||||
|  |     hud->setPlayerPos(x,y); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void WindowManager::setPlayerDir(const float x, const float y) | ||||||
|  | { | ||||||
|  |     map->setPlayerDir(x,y); | ||||||
|  |     hud->setPlayerDir(x,y); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ | ||||||
| #include <openengine/ogre/renderer.hpp> | #include <openengine/ogre/renderer.hpp> | ||||||
| #include <openengine/gui/manager.hpp> | #include <openengine/gui/manager.hpp> | ||||||
| #include "../mwmechanics/stat.hpp" | #include "../mwmechanics/stat.hpp" | ||||||
|  | #include "../mwworld/ptr.hpp" | ||||||
| #include "mode.hpp" | #include "mode.hpp" | ||||||
| 
 | 
 | ||||||
| namespace MyGUI | namespace MyGUI | ||||||
|  | @ -152,6 +153,12 @@ namespace MWGui | ||||||
|     void setBounty (int bounty);                                           ///< set the current bounty value
 |     void setBounty (int bounty);                                           ///< set the current bounty value
 | ||||||
|     void updateSkillArea();                                                ///< update display of skills, factions, birth sign, reputation and bounty
 |     void updateSkillArea();                                                ///< update display of skills, factions, birth sign, reputation and bounty
 | ||||||
| 
 | 
 | ||||||
|  |     void changeCell(MWWorld::Ptr::CellStore* cell); ///< change the active cell
 | ||||||
|  |     void setPlayerPos(const float x, const float y); ///< set player position in map space
 | ||||||
|  |     void setPlayerDir(const float x, const float y); ///< set player view direction in map space
 | ||||||
|  |      | ||||||
|  |     void setInteriorMapTexture(const int x, const int y); | ||||||
|  |     ///< set the index of the map texture that should be used (for interiors)
 | ||||||
| 
 | 
 | ||||||
|     template<typename T> |     template<typename T> | ||||||
|     void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr.
 |     void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr.
 | ||||||
|  |  | ||||||
							
								
								
									
										312
									
								
								apps/openmw/mwrender/localmap.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								apps/openmw/mwrender/localmap.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,312 @@ | ||||||
|  | #include "localmap.hpp" | ||||||
|  | #include "renderingmanager.hpp" | ||||||
|  | 
 | ||||||
|  | #include "../mwworld/environment.hpp" | ||||||
|  | #include "../mwgui/window_manager.hpp" | ||||||
|  | 
 | ||||||
|  | #include <OgreOverlayManager.h> | ||||||
|  | #include <OgreMaterialManager.h> | ||||||
|  | 
 | ||||||
|  | using namespace MWRender; | ||||||
|  | using namespace Ogre; | ||||||
|  | 
 | ||||||
|  | LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWWorld::Environment* env) | ||||||
|  | { | ||||||
|  |     mRendering = rend; | ||||||
|  |     mEnvironment = env; | ||||||
|  |      | ||||||
|  |     mCellCamera = mRendering->getScene()->createCamera("CellCamera"); | ||||||
|  |     mCellCamera->setProjectionType(PT_ORTHOGRAPHIC); | ||||||
|  |     // look down -y
 | ||||||
|  |     const float sqrt0pt5 = 0.707106781; | ||||||
|  |     mCellCamera->setOrientation(Quaternion(sqrt0pt5, -sqrt0pt5, 0, 0)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LocalMap::~LocalMap() | ||||||
|  | { | ||||||
|  |     deleteBuffers(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMap::deleteBuffers() | ||||||
|  | { | ||||||
|  |     for (std::map<std::string, uint32*>::iterator it=mBuffers.begin(); | ||||||
|  |         it != mBuffers.end(); ++it) | ||||||
|  |     { | ||||||
|  |         delete it->second; | ||||||
|  |     } | ||||||
|  |     mBuffers.clear(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMap::saveTexture(const std::string& texname, const std::string& filename) | ||||||
|  | { | ||||||
|  |     TexturePtr tex = TextureManager::getSingleton().getByName(texname); | ||||||
|  |     if (tex.isNull()) return; | ||||||
|  |     HardwarePixelBufferSharedPtr readbuffer = tex->getBuffer(); | ||||||
|  |     readbuffer->lock(HardwareBuffer::HBL_NORMAL ); | ||||||
|  |     const PixelBox &readrefpb = readbuffer->getCurrentLock();     | ||||||
|  |     uchar *readrefdata = static_cast<uchar*>(readrefpb.data);         | ||||||
|  | 
 | ||||||
|  |     Image img; | ||||||
|  |     img = img.loadDynamicImage (readrefdata, tex->getWidth(), | ||||||
|  |         tex->getHeight(), tex->getFormat());     | ||||||
|  |     img.save("./" + filename); | ||||||
|  | 
 | ||||||
|  |     readbuffer->unlock(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string LocalMap::coordStr(const int x, const int y) | ||||||
|  | { | ||||||
|  |     return StringConverter::toString(x) + "_" + StringConverter::toString(y); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMap::saveFogOfWar(MWWorld::Ptr::CellStore* cell) | ||||||
|  | { | ||||||
|  |     if (!mInterior) | ||||||
|  |     { | ||||||
|  |         /*saveTexture("Cell_"+coordStr(mCellX, mCellY)+"_fog",
 | ||||||
|  |             "Cell_"+coordStr(mCellX, mCellY)+"_fog.png");*/ | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z); | ||||||
|  |         Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z); | ||||||
|  |         /// \todo why is this workaround needed?
 | ||||||
|  |         min *= 1.3; | ||||||
|  |         max *= 1.3; | ||||||
|  |         Vector2 length = max-min; | ||||||
|  |          | ||||||
|  |         // divide into segments
 | ||||||
|  |         const int segsX = std::ceil( length.x / sSize ); | ||||||
|  |         const int segsY = std::ceil( length.y / sSize ); | ||||||
|  | 
 | ||||||
|  |         for (int x=0; x<segsX; ++x) | ||||||
|  |         { | ||||||
|  |             for (int y=0; y<segsY; ++y) | ||||||
|  |             { | ||||||
|  |                 /*saveTexture(
 | ||||||
|  |                     mInteriorName + "_" + coordStr(x,y) + "_fog", | ||||||
|  |                     mInteriorName + "_" + coordStr(x,y) + "_fog.png");*/ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell) | ||||||
|  | { | ||||||
|  |     mInterior = false; | ||||||
|  | 
 | ||||||
|  |     std::string name = "Cell_"+coordStr(cell->cell->data.gridX, cell->cell->data.gridY); | ||||||
|  | 
 | ||||||
|  |     int x = cell->cell->data.gridX; | ||||||
|  |     int y = cell->cell->data.gridY; | ||||||
|  | 
 | ||||||
|  |     render((x+0.5)*sSize, (-y-0.5)*sSize, -10000, 10000, sSize, sSize, name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell, | ||||||
|  |                             AxisAlignedBox bounds) | ||||||
|  | { | ||||||
|  |     mInterior = true; | ||||||
|  |     mBounds = bounds; | ||||||
|  |      | ||||||
|  |     Vector2 z(bounds.getMaximum().y, bounds.getMinimum().y); | ||||||
|  |     Vector2 min(bounds.getMinimum().x, bounds.getMinimum().z); | ||||||
|  |     Vector2 max(bounds.getMaximum().x, bounds.getMaximum().z); | ||||||
|  | 
 | ||||||
|  |     /// \todo why is this workaround needed?
 | ||||||
|  |     min *= 1.3; | ||||||
|  |     max *= 1.3; | ||||||
|  | 
 | ||||||
|  |     Vector2 length = max-min; | ||||||
|  |     Vector2 center(bounds.getCenter().x, bounds.getCenter().z); | ||||||
|  | 
 | ||||||
|  |     // divide into segments
 | ||||||
|  |     const int segsX = std::ceil( length.x / sSize ); | ||||||
|  |     const int segsY = std::ceil( length.y / sSize ); | ||||||
|  | 
 | ||||||
|  |     mInteriorName = cell->cell->name; | ||||||
|  | 
 | ||||||
|  |     for (int x=0; x<segsX; ++x) | ||||||
|  |     { | ||||||
|  |         for (int y=0; y<segsY; ++y) | ||||||
|  |         { | ||||||
|  |             Vector2 start = min + Vector2(sSize*x,sSize*y); | ||||||
|  |             Vector2 newcenter = start + 4096; | ||||||
|  | 
 | ||||||
|  |             render(newcenter.x, newcenter.y, z.y, z.x, sSize, sSize, | ||||||
|  |                 cell->cell->name + "_" + coordStr(x,y)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMap::render(const float x, const float y, | ||||||
|  |                     const float zlow, const float zhigh, | ||||||
|  |                     const float xw, const float yw, const std::string& texture) | ||||||
|  | { | ||||||
|  |     // disable fog
 | ||||||
|  |     // changing FOG_MODE is not a solution when using shaders, thus we have to push linear start/end
 | ||||||
|  |     const float fStart = mRendering->getScene()->getFogStart(); | ||||||
|  |     const float fEnd = mRendering->getScene()->getFogEnd(); | ||||||
|  |     const ColourValue& clr = mRendering->getScene()->getFogColour(); | ||||||
|  |     mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, 1000000, 10000000); | ||||||
|  | 
 | ||||||
|  |     // make everything visible
 | ||||||
|  |     mRendering->getScene()->setAmbientLight(ColourValue(1,1,1)); | ||||||
|  | 
 | ||||||
|  |     mCellCamera->setPosition(Vector3(x, zhigh+100000, y)); | ||||||
|  |     //mCellCamera->setFarClipDistance( (zhigh-zlow) * 1.1 );
 | ||||||
|  |     mCellCamera->setFarClipDistance(0); // infinite
 | ||||||
|  | 
 | ||||||
|  |     mCellCamera->setOrthoWindow(xw, yw); | ||||||
|  | 
 | ||||||
|  |     TexturePtr tex; | ||||||
|  |     // try loading from memory
 | ||||||
|  |     tex = TextureManager::getSingleton().getByName(texture); | ||||||
|  |     if (tex.isNull()) | ||||||
|  |     { | ||||||
|  |         // try loading from disk
 | ||||||
|  |         //if (boost::filesystem::exists(texture+".jpg"))
 | ||||||
|  |         //{
 | ||||||
|  |             /// \todo
 | ||||||
|  |         //}
 | ||||||
|  |         //else
 | ||||||
|  |         { | ||||||
|  |             // render
 | ||||||
|  |             tex = TextureManager::getSingleton().createManual( | ||||||
|  |                             texture, | ||||||
|  |                             ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, | ||||||
|  |                             TEX_TYPE_2D, | ||||||
|  |                             xw*sMapResolution/sSize, yw*sMapResolution/sSize,  | ||||||
|  |                             0, | ||||||
|  |                             PF_R8G8B8, | ||||||
|  |                             TU_RENDERTARGET); | ||||||
|  | 
 | ||||||
|  |             RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); | ||||||
|  |             rtt->setAutoUpdated(false); | ||||||
|  |             Viewport* vp = rtt->addViewport(mCellCamera); | ||||||
|  |             vp->setOverlaysEnabled(false); | ||||||
|  |             vp->setShadowsEnabled(false); | ||||||
|  |             vp->setBackgroundColour(ColourValue(0, 0, 0)); | ||||||
|  |             //vp->setVisibilityMask( ... );
 | ||||||
|  | 
 | ||||||
|  |             rtt->update(); | ||||||
|  | 
 | ||||||
|  |             // create "fog of war" texture
 | ||||||
|  |             TexturePtr tex2 = TextureManager::getSingleton().createManual( | ||||||
|  |                             texture + "_fog", | ||||||
|  |                             ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, | ||||||
|  |                             TEX_TYPE_2D, | ||||||
|  |                             xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize,  | ||||||
|  |                             0, | ||||||
|  |                             PF_A8R8G8B8, | ||||||
|  |                             TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); | ||||||
|  | 
 | ||||||
|  |             // create a buffer to use for dynamic operations
 | ||||||
|  |             uint32* buffer = new uint32[sFogOfWarResolution*sFogOfWarResolution]; | ||||||
|  | 
 | ||||||
|  |             // initialize to (0, 0, 0, 1)
 | ||||||
|  |             uint32* pointer = buffer; | ||||||
|  |             for (int p=0; p<sFogOfWarResolution*sFogOfWarResolution; ++p) | ||||||
|  |             { | ||||||
|  |                 *(pointer+p) = (255 << 24); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             memcpy(tex2->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), buffer, sFogOfWarResolution*sFogOfWarResolution*4); | ||||||
|  |             tex2->getBuffer()->unlock(); | ||||||
|  | 
 | ||||||
|  |             mBuffers[texture] = buffer; | ||||||
|  | 
 | ||||||
|  |             // save to cache for next time
 | ||||||
|  |             //rtt->writeContentsToFile("./" + texture + ".jpg");
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |     // re-enable fog
 | ||||||
|  |     mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction) | ||||||
|  | { | ||||||
|  |     if (sFogOfWarSkip != 0) | ||||||
|  |     { | ||||||
|  |         static int count=0; | ||||||
|  |         if (++count % sFogOfWarSkip != 0) | ||||||
|  |             return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // retrieve the x,y grid coordinates the player is in 
 | ||||||
|  |     int x,y; | ||||||
|  |     Vector2 pos(position.x, position.z); | ||||||
|  |     if (!mInterior) | ||||||
|  |     { | ||||||
|  |         x = std::ceil(pos.x / sSize)-1; | ||||||
|  |         y = std::ceil(-pos.y / sSize)-1; | ||||||
|  |         mCellX = x; | ||||||
|  |         mCellY = y; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z); | ||||||
|  |         min *= 1.3; | ||||||
|  |          | ||||||
|  |         x = std::ceil((pos.x - min.x)/sSize)-1; | ||||||
|  |         y = std::ceil((pos.y - min.y)/sSize)-1; | ||||||
|  | 
 | ||||||
|  |         mEnvironment->mWindowManager->setInteriorMapTexture(x,y); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // convert from world coordinates to texture UV coordinates
 | ||||||
|  |     float u,v; | ||||||
|  |     std::string texName; | ||||||
|  |     if (!mInterior) | ||||||
|  |     { | ||||||
|  |         u = std::abs((pos.x - (sSize*x))/sSize); | ||||||
|  |         v = 1-std::abs((pos.y + (sSize*y))/sSize); | ||||||
|  |         texName = "Cell_"+coordStr(x,y); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z); | ||||||
|  |         min *= 1.3; | ||||||
|  | 
 | ||||||
|  |         u = (pos.x - min.x - sSize*x)/sSize; | ||||||
|  |         v = (pos.y - min.y - sSize*y)/sSize; | ||||||
|  | 
 | ||||||
|  |         texName = mInteriorName + "_" + coordStr(x,y); | ||||||
|  |     } | ||||||
|  |     mEnvironment->mWindowManager->setPlayerPos(u, v); | ||||||
|  |     mEnvironment->mWindowManager->setPlayerDir(direction.x, -direction.z); | ||||||
|  | 
 | ||||||
|  |     // explore radius (squared)
 | ||||||
|  |     const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution; | ||||||
|  | 
 | ||||||
|  |     // get the appropriate fog of war texture
 | ||||||
|  |     TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog"); | ||||||
|  |     if (!tex.isNull()) | ||||||
|  |     { | ||||||
|  |         // get its buffer
 | ||||||
|  |         if (mBuffers.find(texName) == mBuffers.end()) return; | ||||||
|  |         uint32* buffer = mBuffers[texName]; | ||||||
|  |         uint32* pointer = buffer; | ||||||
|  |         for (int texV = 0; texV<sFogOfWarResolution; ++texV) | ||||||
|  |         { | ||||||
|  |             for (int texU = 0; texU<sFogOfWarResolution; ++texU) | ||||||
|  |             { | ||||||
|  |                 float sqrDist = Math::Sqr(texU - u*sFogOfWarResolution) + Math::Sqr(texV - v*sFogOfWarResolution); | ||||||
|  |                 uint32 clr = *pointer; | ||||||
|  |                 uint8 alpha = (clr >> 24); | ||||||
|  |                 alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); | ||||||
|  |                 *((uint32*)pointer) = (alpha << 24); | ||||||
|  | 
 | ||||||
|  |                 // move to next texel
 | ||||||
|  |                 ++pointer; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // copy to the texture
 | ||||||
|  |         memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), buffer, sFogOfWarResolution*sFogOfWarResolution*4); | ||||||
|  |         tex->getBuffer()->unlock(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										100
									
								
								apps/openmw/mwrender/localmap.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								apps/openmw/mwrender/localmap.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | ||||||
|  | #ifndef _GAME_RENDER_LOCALMAP_H | ||||||
|  | #define _GAME_RENDER_LOCALMAP_H | ||||||
|  | 
 | ||||||
|  | #include "../mwworld/ptr.hpp" | ||||||
|  | 
 | ||||||
|  | #include <openengine/ogre/renderer.hpp> | ||||||
|  | 
 | ||||||
|  | namespace MWWorld | ||||||
|  | { | ||||||
|  |     class Environment; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | namespace MWRender | ||||||
|  | { | ||||||
|  |     ///
 | ||||||
|  |     /// \brief Local map rendering
 | ||||||
|  |     ///
 | ||||||
|  |     class LocalMap | ||||||
|  |     { | ||||||
|  |     public: | ||||||
|  |         LocalMap(OEngine::Render::OgreRenderer*, MWWorld::Environment* env); | ||||||
|  |         ~LocalMap(); | ||||||
|  | 
 | ||||||
|  |         /**
 | ||||||
|  |          * Request the local map for an exterior cell. | ||||||
|  |          * @remarks It will either be loaded from a disk cache, | ||||||
|  |          * or rendered if it is not already cached. | ||||||
|  |          * @param exterior cell | ||||||
|  |          */ | ||||||
|  |         void requestMap (MWWorld::Ptr::CellStore* cell); | ||||||
|  | 
 | ||||||
|  |         /**
 | ||||||
|  |          * Request the local map for an interior cell. | ||||||
|  |          * @remarks It will either be loaded from a disk cache, | ||||||
|  |          * or rendered if it is not already cached. | ||||||
|  |          * @param interior cell | ||||||
|  |          * @param bounding box of the cell | ||||||
|  |          */ | ||||||
|  |         void requestMap (MWWorld::Ptr::CellStore* cell, | ||||||
|  |                         Ogre::AxisAlignedBox bounds); | ||||||
|  | 
 | ||||||
|  |         /**
 | ||||||
|  |          * Set the position & direction of the player. | ||||||
|  |          * @remarks This is used to draw a "fog of war" effect | ||||||
|  |          * to hide areas on the map the player has not discovered yet. | ||||||
|  |          * @param position (OGRE coordinates) | ||||||
|  |          * @param view direction (OGRE coordinates) | ||||||
|  |          */ | ||||||
|  |         void updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction); | ||||||
|  | 
 | ||||||
|  |         /**
 | ||||||
|  |          * Save the fog of war for the current cell to disk. | ||||||
|  |          * @remarks This should be called before loading a | ||||||
|  |          * new cell, as well as when the game is quit. | ||||||
|  |          * @param current cell | ||||||
|  |          */ | ||||||
|  |         void saveFogOfWar(MWWorld::Ptr::CellStore* cell); | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         OEngine::Render::OgreRenderer* mRendering; | ||||||
|  |         MWWorld::Environment* mEnvironment; | ||||||
|  | 
 | ||||||
|  |         // 1024*1024 pixels for a cell
 | ||||||
|  |         static const int sMapResolution = 1024; | ||||||
|  | 
 | ||||||
|  |         // the dynamic texture is a bottleneck, so don't set this too high
 | ||||||
|  |         static const int sFogOfWarResolution = 32; | ||||||
|  | 
 | ||||||
|  |         // frames to skip before rendering fog of war
 | ||||||
|  |         static const int sFogOfWarSkip = 2; | ||||||
|  | 
 | ||||||
|  |         // size of a map segment (for exteriors, 1 cell)
 | ||||||
|  |         static const int sSize = 8192; | ||||||
|  | 
 | ||||||
|  |         Ogre::Camera* mCellCamera; | ||||||
|  | 
 | ||||||
|  |         void render(const float x, const float y, | ||||||
|  |                     const float zlow, const float zhigh, | ||||||
|  |                     const float xw, const float yw, | ||||||
|  |                     const std::string& texture); | ||||||
|  | 
 | ||||||
|  |         void saveTexture(const std::string& texname, const std::string& filename); | ||||||
|  | 
 | ||||||
|  |         std::string coordStr(const int x, const int y); | ||||||
|  | 
 | ||||||
|  |         // a buffer for the "fog of war" texture of the current cell.
 | ||||||
|  |         // interior cells could be divided into multiple textures,
 | ||||||
|  |         // so we store in a map.
 | ||||||
|  |         std::map <std::string, Ogre::uint32*> mBuffers; | ||||||
|  | 
 | ||||||
|  |         void deleteBuffers(); | ||||||
|  | 
 | ||||||
|  |         bool mInterior; | ||||||
|  |         int mCellX, mCellY; | ||||||
|  |         Ogre::AxisAlignedBox mBounds; | ||||||
|  |         std::string mInteriorName; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | @ -109,6 +109,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) | ||||||
|             // If it is set too low:
 |             // If it is set too low:
 | ||||||
|             //  - there will be too many batches.
 |             //  - there will be too many batches.
 | ||||||
|             sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); |             sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); | ||||||
|  | 
 | ||||||
|  |             mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; | ||||||
|  |             mBounds[ptr.getCell()].merge(ent->getBoundingBox()); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|  | @ -116,6 +119,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); |         sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); | ||||||
|  |         mBounds[ptr.getCell()].merge(insert->_getDerivedPosition()); | ||||||
| 
 | 
 | ||||||
|         mRenderer.getScene()->destroyEntity(ent); |         mRenderer.getScene()->destroyEntity(ent); | ||||||
|     } |     } | ||||||
|  | @ -202,6 +206,9 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store) | ||||||
|         mRenderer.getScene()->destroyStaticGeometry (sg); |         mRenderer.getScene()->destroyStaticGeometry (sg); | ||||||
|         sg = 0; |         sg = 0; | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     if(mBounds.find(store) != mBounds.end()) | ||||||
|  |         mBounds.erase(store); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell) | void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell) | ||||||
|  | @ -212,3 +219,8 @@ void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell) | ||||||
|         sg->build(); |         sg->build(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell) | ||||||
|  | { | ||||||
|  |     return mBounds[cell]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ class Objects{ | ||||||
|     OEngine::Render::OgreRenderer &mRenderer; |     OEngine::Render::OgreRenderer &mRenderer; | ||||||
|     std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes; |     std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes; | ||||||
|     std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry; |     std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry; | ||||||
|  |     std::map<MWWorld::Ptr::CellStore *, Ogre::AxisAlignedBox> mBounds; | ||||||
|     Ogre::SceneNode* mMwRoot; |     Ogre::SceneNode* mMwRoot; | ||||||
|     bool mIsStatic; |     bool mIsStatic; | ||||||
|     static int uniqueID; |     static int uniqueID; | ||||||
|  | @ -42,6 +43,9 @@ public: | ||||||
|     void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); |     void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); | ||||||
|     void insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius); |     void insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius); | ||||||
| 
 | 
 | ||||||
|  |     Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*); | ||||||
|  |     ///< get a bounding box that encloses all objects in the specified cell
 | ||||||
|  | 
 | ||||||
|     bool deleteObject (const MWWorld::Ptr& ptr); |     bool deleteObject (const MWWorld::Ptr& ptr); | ||||||
|     ///< \return found?
 |     ///< \return found?
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -60,6 +60,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const | ||||||
| 
 | 
 | ||||||
|     mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); |     mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); | ||||||
|     mSun = 0; |     mSun = 0; | ||||||
|  | 
 | ||||||
|  |     mLocalMap = new MWRender::LocalMap(&mRendering, &environment); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RenderingManager::~RenderingManager () | RenderingManager::~RenderingManager () | ||||||
|  | @ -68,6 +70,7 @@ RenderingManager::~RenderingManager () | ||||||
|     delete mPlayer; |     delete mPlayer; | ||||||
|     delete mSkyManager; |     delete mSkyManager; | ||||||
|     delete mTerrainManager; |     delete mTerrainManager; | ||||||
|  |     delete mLocalMap; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MWRender::SkyManager* RenderingManager::getSkyManager() | MWRender::SkyManager* RenderingManager::getSkyManager() | ||||||
|  | @ -147,6 +150,8 @@ void RenderingManager::update (float duration){ | ||||||
|     mSkyManager->update(duration); |     mSkyManager->update(duration); | ||||||
|      |      | ||||||
|     mRendering.update(duration); |     mRendering.update(duration); | ||||||
|  | 
 | ||||||
|  |     mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RenderingManager::skyEnable () | void RenderingManager::skyEnable () | ||||||
|  | @ -339,4 +344,17 @@ void RenderingManager::setGlare(bool glare) | ||||||
|     mSkyManager->setGlare(glare); |     mSkyManager->setGlare(glare); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell) | ||||||
|  | { | ||||||
|  |     if (!(cell->cell->data.flags & ESM::Cell::Interior)) | ||||||
|  |         mLocalMap->requestMap(cell); | ||||||
|  |     else | ||||||
|  |         mLocalMap->requestMap(cell, mObjects.getDimensions(cell)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell) | ||||||
|  | { | ||||||
|  |     mLocalMap->saveFogOfWar(cell); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ | ||||||
| #include "objects.hpp" | #include "objects.hpp" | ||||||
| #include "actors.hpp" | #include "actors.hpp" | ||||||
| #include "player.hpp" | #include "player.hpp" | ||||||
|  | #include "localmap.hpp" | ||||||
| 
 | 
 | ||||||
| namespace Ogre | namespace Ogre | ||||||
| { | { | ||||||
|  | @ -76,6 +77,9 @@ class RenderingManager: private RenderingInterface { | ||||||
|     /// when rebatching is needed and update automatically at the end of each frame.
 |     /// when rebatching is needed and update automatically at the end of each frame.
 | ||||||
|     void cellAdded (MWWorld::Ptr::CellStore *store); |     void cellAdded (MWWorld::Ptr::CellStore *store); | ||||||
| 
 | 
 | ||||||
|  |     void preCellChange (MWWorld::Ptr::CellStore* store); | ||||||
|  |     ///< this event is fired immediately before changing cell
 | ||||||
|  | 
 | ||||||
|     void addObject (const MWWorld::Ptr& ptr); |     void addObject (const MWWorld::Ptr& ptr); | ||||||
|     void removeObject (const MWWorld::Ptr& ptr); |     void removeObject (const MWWorld::Ptr& ptr); | ||||||
| 
 | 
 | ||||||
|  | @ -104,6 +108,9 @@ class RenderingManager: private RenderingInterface { | ||||||
|     void skySetMoonColour (bool red); |     void skySetMoonColour (bool red); | ||||||
|     void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell); |     void configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell); | ||||||
| 
 | 
 | ||||||
|  |     void requestMap (MWWorld::Ptr::CellStore* cell); | ||||||
|  |     ///< request the local map for a cell
 | ||||||
|  |      | ||||||
|     /// configure fog according to cell
 |     /// configure fog according to cell
 | ||||||
|     void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell); |     void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell); | ||||||
|      |      | ||||||
|  | @ -150,6 +157,8 @@ class RenderingManager: private RenderingInterface { | ||||||
| 
 | 
 | ||||||
|     MWRender::Player *mPlayer; |     MWRender::Player *mPlayer; | ||||||
|     MWRender::Debugging mDebugging; |     MWRender::Debugging mDebugging; | ||||||
|  | 
 | ||||||
|  |     MWRender::LocalMap* mLocalMap; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -446,6 +446,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environmen | ||||||
|     vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); |     vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); | ||||||
|     vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); |     vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); | ||||||
|     mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); |     mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); | ||||||
|  |     mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(""); | ||||||
| 
 | 
 | ||||||
|     // Clouds
 |     // Clouds
 | ||||||
|     NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); |     NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); | ||||||
|  |  | ||||||
|  | @ -6,6 +6,8 @@ | ||||||
| 
 | 
 | ||||||
| #include "../mwsound/soundmanager.hpp" | #include "../mwsound/soundmanager.hpp" | ||||||
| 
 | 
 | ||||||
|  | #include "../mwgui/window_manager.hpp" | ||||||
|  | 
 | ||||||
| #include "ptr.hpp" | #include "ptr.hpp" | ||||||
| #include "environment.hpp" | #include "environment.hpp" | ||||||
| #include "player.hpp" | #include "player.hpp" | ||||||
|  | @ -101,7 +103,8 @@ namespace MWWorld | ||||||
|               insertCell(*cell, mEnvironment); |               insertCell(*cell, mEnvironment); | ||||||
|                mRendering.cellAdded (cell); |                mRendering.cellAdded (cell); | ||||||
|                mRendering.configureAmbient(*cell); |                mRendering.configureAmbient(*cell); | ||||||
| 
 |                mRendering.requestMap(cell); | ||||||
|  |                mRendering.configureAmbient(*cell); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -117,10 +120,14 @@ namespace MWWorld | ||||||
|         // TODO orientation
 |         // TODO orientation
 | ||||||
|         mEnvironment.mMechanicsManager->addActor (mWorld->getPlayer().getPlayer()); |         mEnvironment.mMechanicsManager->addActor (mWorld->getPlayer().getPlayer()); | ||||||
|         mEnvironment.mMechanicsManager->watchActor (mWorld->getPlayer().getPlayer()); |         mEnvironment.mMechanicsManager->watchActor (mWorld->getPlayer().getPlayer()); | ||||||
|  | 
 | ||||||
|  |         mEnvironment.mWindowManager->changeCell( mCurrentCell ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) |     void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) | ||||||
|     { |     { | ||||||
|  |         mRendering.preCellChange(mCurrentCell); | ||||||
|  | 
 | ||||||
|         // remove active
 |         // remove active
 | ||||||
|         mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer()); |         mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -299,7 +299,138 @@ void NIFLoader::createMaterial(const String &name, | ||||||
|     material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]); |     material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]); | ||||||
|     material->setShininess(glossiness); |     material->setShininess(glossiness); | ||||||
| 
 | 
 | ||||||
|  |     // Create shader for the material
 | ||||||
|  |     // vertex
 | ||||||
|  |     HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); | ||||||
| 
 | 
 | ||||||
|  |     HighLevelGpuProgramPtr vertex; | ||||||
|  |     if (mgr.getByName("main_vp").isNull()) | ||||||
|  |     { | ||||||
|  |         vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, | ||||||
|  |             "cg", GPT_VERTEX_PROGRAM); | ||||||
|  |         vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1"); | ||||||
|  |         vertex->setParameter("entry_point", "main_vp"); | ||||||
|  |         StringUtil::StrStreamType outStream; | ||||||
|  |         outStream << | ||||||
|  |         "void main_vp(	\n" | ||||||
|  |         "	float4 position : POSITION,	\n" | ||||||
|  |         "   float4 normal : NORMAL, \n" | ||||||
|  |         "   float4 colour : COLOR, \n" | ||||||
|  |         "   in float2 uv : TEXCOORD0, \n" | ||||||
|  |         "   out float2 oUV : TEXCOORD0, \n" | ||||||
|  |         "	out float4 oPosition : POSITION,	\n" | ||||||
|  |         "   out float4 oPositionObjSpace : TEXCOORD1, \n" | ||||||
|  |         "   out float4 oNormal : TEXCOORD2, \n" | ||||||
|  |         "   out float oFogValue : TEXCOORD3, \n" | ||||||
|  |         "   out float4 oVertexColour : TEXCOORD4, \n" | ||||||
|  |         "   uniform float4 fogParams, \n" | ||||||
|  |         "	uniform float4x4 worldViewProj	\n" | ||||||
|  |         ")	\n" | ||||||
|  |         "{	\n" | ||||||
|  |         "   oVertexColour = colour; \n" | ||||||
|  |         "   oUV = uv; \n" | ||||||
|  |         "   oNormal = normal; \n" | ||||||
|  |         "	oPosition = mul( worldViewProj, position );  \n" | ||||||
|  |         "   oFogValue = saturate((oPosition.z - fogParams.y) * fogParams.w); \n" | ||||||
|  |         "   oPositionObjSpace = position; \n" | ||||||
|  |         "}"; | ||||||
|  |         vertex->setSource(outStream.str()); | ||||||
|  |         vertex->load(); | ||||||
|  |         vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); | ||||||
|  |         vertex->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |         vertex = mgr.getByName("main_vp"); | ||||||
|  |     material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName()); | ||||||
|  | 
 | ||||||
|  |     // the number of lights to support.
 | ||||||
|  |     // when rendering an object, OGRE automatically picks the lights that are
 | ||||||
|  |     // closest to the object being rendered. unfortunately this mechanism does
 | ||||||
|  |     // not work perfectly for objects batched together (they will all use the same
 | ||||||
|  |     // lights). to work around this, we are simply pushing the maximum number
 | ||||||
|  |     // of lights here in order to minimize disappearing lights.
 | ||||||
|  |     float num_lights; | ||||||
|  |     if (GpuProgramManager::getSingleton().isSyntaxSupported("fp40") || | ||||||
|  |         GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0")) | ||||||
|  |         num_lights = 8 /* 32 */; | ||||||
|  |     else | ||||||
|  |         num_lights = 8; | ||||||
|  | 
 | ||||||
|  |     // fragment
 | ||||||
|  |     HighLevelGpuProgramPtr fragment; | ||||||
|  |     if (mgr.getByName("main_fp").isNull()) | ||||||
|  |     { | ||||||
|  |         fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, | ||||||
|  |             "cg", GPT_FRAGMENT_PROGRAM); | ||||||
|  |         fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1"); | ||||||
|  |         fragment->setParameter("entry_point", "main_fp"); | ||||||
|  |         StringUtil::StrStreamType outStream; | ||||||
|  |         outStream << | ||||||
|  |         "void main_fp(	\n" | ||||||
|  |         "   in float2 uv : TEXCOORD0, \n" | ||||||
|  |         "	out float4 oColor    : COLOR, \n" | ||||||
|  |         "   uniform sampler2D texture : TEXUNIT0, \n" | ||||||
|  |         "   float4 positionObjSpace : TEXCOORD1, \n" | ||||||
|  |         "   float4 normal : TEXCOORD2, \n" | ||||||
|  |         "   float fogValue : TEXCOORD3, \n" | ||||||
|  |         "   float4 vertexColour : TEXCOORD4, \n" | ||||||
|  |         "   uniform float4 fogColour, \n"; | ||||||
|  | 
 | ||||||
|  |         for (int i=0; i<num_lights; ++i) | ||||||
|  |         { | ||||||
|  |             outStream << | ||||||
|  |             "   uniform float4 lightDiffuse"<<i<<", \n" | ||||||
|  |             "   uniform float4 lightPositionObjSpace"<<i<<", \n" | ||||||
|  |             "   uniform float4 lightAttenuation"<<i<<", \n"; | ||||||
|  |         } | ||||||
|  |         outStream << | ||||||
|  |         "   uniform float4 lightAmbient, \n" | ||||||
|  |         "   uniform float4 ambient, \n" | ||||||
|  |         "   uniform float4 diffuse, \n" | ||||||
|  |         "   uniform float4 emissive \n" | ||||||
|  |         ")	\n" | ||||||
|  |         "{	\n" | ||||||
|  |         "   float4 tex =  tex2D(texture, uv); \n" | ||||||
|  |         "   float d; \n" | ||||||
|  |         "   float attn; \n" | ||||||
|  |         "   float3 lightColour = float3(0, 0, 0); \n"; | ||||||
|  |          | ||||||
|  |         for (int i=0; i<num_lights; ++i) | ||||||
|  |         { | ||||||
|  |             outStream << | ||||||
|  |             "   float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n" | ||||||
|  | 
 | ||||||
|  |             // pre-multiply light color with attenuation factor
 | ||||||
|  |             "   d = length( lightDir"<<i<<" ); \n" | ||||||
|  |             "   attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n" | ||||||
|  |             "   lightDiffuse"<<i<<" *= attn; \n" | ||||||
|  | 
 | ||||||
|  |             "	lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n"; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         outStream << | ||||||
|  |         "   float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n" | ||||||
|  |         "   oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n" | ||||||
|  |         "   oColor.a = tex.a * diffuse.a * vertexColour.a; \n" | ||||||
|  |         "}"; | ||||||
|  |         fragment->setSource(outStream.str()); | ||||||
|  |         fragment->load(); | ||||||
|  | 
 | ||||||
|  |         for (int i=0; i<num_lights; ++i) | ||||||
|  |         { | ||||||
|  |             fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i); | ||||||
|  |             fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i); | ||||||
|  |             fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i); | ||||||
|  |         } | ||||||
|  |         fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); | ||||||
|  |         fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); | ||||||
|  |         fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR); | ||||||
|  |         fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); | ||||||
|  |         fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |         fragment = mgr.getByName("main_fp"); | ||||||
|  |     material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Takes a name and adds a unique part to it. This is just used to
 | // Takes a name and adds a unique part to it. This is just used to
 | ||||||
|  |  | ||||||
|  | @ -42,6 +42,7 @@ configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY) | ||||||
| configure_file("${SDIR}/openmw_mainmenu_layout.xml" "${DDIR}/openmw_mainmenu_layout.xml" COPYONLY) | configure_file("${SDIR}/openmw_mainmenu_layout.xml" "${DDIR}/openmw_mainmenu_layout.xml" COPYONLY) | ||||||
| configure_file("${SDIR}/openmw_mainmenu_skin.xml" "${DDIR}/openmw_mainmenu_skin.xml" COPYONLY) | configure_file("${SDIR}/openmw_mainmenu_skin.xml" "${DDIR}/openmw_mainmenu_skin.xml" COPYONLY) | ||||||
| configure_file("${SDIR}/openmw_map_window_layout.xml" "${DDIR}/openmw_map_window_layout.xml" COPYONLY) | configure_file("${SDIR}/openmw_map_window_layout.xml" "${DDIR}/openmw_map_window_layout.xml" COPYONLY) | ||||||
|  | configure_file("${SDIR}/openmw_map_window_skin.xml" "${DDIR}/openmw_map_window_skin.xml" COPYONLY) | ||||||
| configure_file("${SDIR}/openmw.pointer.xml" "${DDIR}/openmw.pointer.xml" COPYONLY) | configure_file("${SDIR}/openmw.pointer.xml" "${DDIR}/openmw.pointer.xml" COPYONLY) | ||||||
| configure_file("${SDIR}/openmw_progress.skin.xml" "${DDIR}/openmw_progress.skin.xml" COPYONLY) | configure_file("${SDIR}/openmw_progress.skin.xml" "${DDIR}/openmw_progress.skin.xml" COPYONLY) | ||||||
| configure_file("${SDIR}/openmw_stats_window_layout.xml" "${DDIR}/openmw_stats_window_layout.xml" COPYONLY) | configure_file("${SDIR}/openmw_stats_window_layout.xml" "${DDIR}/openmw_stats_window_layout.xml" COPYONLY) | ||||||
|  |  | ||||||
|  | @ -14,4 +14,7 @@ | ||||||
|         <BasisSkin type="MainSkin" offset = "0 0 16 16"/> |         <BasisSkin type="MainSkin" offset = "0 0 16 16"/> | ||||||
|     </Skin> |     </Skin> | ||||||
| 
 | 
 | ||||||
|  |     <Skin name = "RotatingSkin" size = "16 16"> | ||||||
|  |         <BasisSkin type="RotatingSkin" offset="0 0 16 16" align="Stretch"/> | ||||||
|  |     </Skin> | ||||||
| </MyGUI> | </MyGUI> | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ | ||||||
|             <List file="openmw_mainmenu_skin.xml" group="General"/> |             <List file="openmw_mainmenu_skin.xml" group="General"/> | ||||||
|             <List file="openmw_console.skin.xml" group="General"/> |             <List file="openmw_console.skin.xml" group="General"/> | ||||||
|             <List file="openmw_journal_skin.xml" group="General"/> |             <List file="openmw_journal_skin.xml" group="General"/> | ||||||
|  |             <List file="openmw_map_window_skin.xml" group="General"/> | ||||||
|             <List file="openmw_dialogue_window_skin.xml" group="General"/> |             <List file="openmw_dialogue_window_skin.xml" group="General"/> | ||||||
|             <List file="openmw_settings.xml" group="General"/> |             <List file="openmw_settings.xml" group="General"/> | ||||||
|       </MyGUI> |       </MyGUI> | ||||||
|  |  | ||||||
|  | @ -38,10 +38,48 @@ | ||||||
|         <!-- Map box --> |         <!-- Map box --> | ||||||
|         <Widget type="Widget" skin="HUD_Box" position="223 123 65 65" |         <Widget type="Widget" skin="HUD_Box" position="223 123 65 65" | ||||||
|             align="Right Bottom"> |             align="Right Bottom"> | ||||||
|             <Widget type="ImageBox" skin="ImageBox" position="2 2 61 61" align="Left Bottom" | 
 | ||||||
|                 name="MiniMap"/> |             <Widget type="ScrollView" skin="MW_MapView" position="2 2 61 61" align="Left Bottom" name="MiniMap"> | ||||||
|             <Widget type="ImageBox" skin="ImageBox" position="17 18 32 32" align="Left Bottom" |                 <Property key="CanvasSize" value="1536 1536"/> | ||||||
|                 name="Compass"/> |                <!-- 3x3 maps, 1024x1024 each, but we will downsample to 512 to antialias them --> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_0"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_0_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="512 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_0"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_0_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="1024 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_0"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_0_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 512 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_1"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_1_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="512 512 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_1"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_1_fog"> | ||||||
|  |                         <Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="Left Bottom" name="Compass"/> | ||||||
|  |                     </Widget> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="1024 512 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_1"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_1_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 1024 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_2"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_2_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="512 1024 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_2"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_2_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  | 
 | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="1024 1024 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_2"> | ||||||
|  |                     <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_2_fog"/> | ||||||
|  |                 </Widget> | ||||||
|  |             </Widget> | ||||||
|         </Widget> |         </Widget> | ||||||
| 
 | 
 | ||||||
|         <!-- Crosshair --> |         <!-- Crosshair --> | ||||||
|  |  | ||||||
|  | @ -197,7 +197,7 @@ | ||||||
|         <Child type="ScrollBar" skin="MW_VScroll" offset = "498 3 14 509" align = "ALIGN_RIGHT ALIGN_VSTRETCH" name = "VScroll"> |         <Child type="ScrollBar" skin="MW_VScroll" offset = "498 3 14 509" align = "ALIGN_RIGHT ALIGN_VSTRETCH" name = "VScroll"> | ||||||
|         </Child> |         </Child> | ||||||
| 
 | 
 | ||||||
|         <Child type="Widget" skin="ClientDefaultSkin" offset = "3 3 493 509" align = "ALIGN_STRETCH" name = "Client"> |         <Child type="Widget" skin="" offset = "3 3 493 509" align = "ALIGN_STRETCH" name = "Client"> | ||||||
|         </Child> |         </Child> | ||||||
| 
 | 
 | ||||||
|         <Child type="Widget" skin="IB_T" offset="2 0 512 2" align="ALIGN_TOP ALIGN_HSTRETCH"/> |         <Child type="Widget" skin="IB_T" offset="2 0 512 2" align="ALIGN_TOP ALIGN_HSTRETCH"/> | ||||||
|  | @ -233,7 +233,7 @@ | ||||||
| 
 | 
 | ||||||
|         <Property key="SkinList" value = "MW_MultiSubList" /> |         <Property key="SkinList" value = "MW_MultiSubList" /> | ||||||
| 
 | 
 | ||||||
|         <Child type="Widget" skin="ClientDefaultSkin" offset = "3 3 516 516" align = "ALIGN_STRETCH" name = "Client"> |         <Child type="Widget" skin="" offset = "3 3 516 516" align = "ALIGN_STRETCH" name = "Client"> | ||||||
|         </Child> |         </Child> | ||||||
| 
 | 
 | ||||||
|         <Child type="Widget" skin="IB_T" offset="2 0 512 2" align="ALIGN_TOP ALIGN_HSTRETCH"/> |         <Child type="Widget" skin="IB_T" offset="2 0 512 2" align="ALIGN_TOP ALIGN_HSTRETCH"/> | ||||||
|  |  | ||||||
|  | @ -2,8 +2,60 @@ | ||||||
| 
 | 
 | ||||||
| <MyGUI type="Layout"> | <MyGUI type="Layout"> | ||||||
|     <Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 300 300" name="_Main"> |     <Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 300 300" name="_Main"> | ||||||
|         <Widget type="ImageBox" skin="ImageBox" position="0 0 284 264" align="ALIGN_STRETCH" name="Map"/> | 
 | ||||||
|         <Widget type="ImageBox" skin="ImageBox" position="126 116 32 32" align="Center" name="Compass"/> |         <!-- Global map --> | ||||||
|  |         <Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="ALIGN_STRETCH" name="GlobalMap"> | ||||||
|  |         </Widget> | ||||||
|  | 
 | ||||||
|  |         <!-- Local map --> | ||||||
|  |         <Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="ALIGN_STRETCH" name="LocalMap"> | ||||||
|  |             <Property key="CanvasSize" value="1536 1536"/> | ||||||
|  | 
 | ||||||
|  |             <!-- 3x3 maps, 1024x1024 each, but we will downsample to 512 to antialias them --> | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_0"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_0_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="512 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_0"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_0_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="1024 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_0"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_0_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="0 512 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_1"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_1_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="512 512 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_1"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_1_fog"> | ||||||
|  |                     <!-- Player arrow --> | ||||||
|  |                     <Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="ALIGN_TOP ALIGN_LEFT" name="Compass"/> | ||||||
|  |                 </Widget> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="1024 512 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_1"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_1_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="0 1024 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_2"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_0_2_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="512 1024 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_2"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_1_2_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="ImageBox" skin="ImageBox" position="1024 1024 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_2"> | ||||||
|  |                 <Widget type="ImageBox" skin="ImageBox" position="0 0 512 512" align="ALIGN_TOP ALIGN_LEFT" name="Map_2_2_fog"/> | ||||||
|  |             </Widget> | ||||||
|  | 
 | ||||||
|  |             <Widget type="Button" skin="" position="0 0 1536 1536" name="EventBox" align="ALIGN_STRETCH"/> | ||||||
|  |         </Widget> | ||||||
|  | 
 | ||||||
|  |         <!-- World button --> | ||||||
|         <Widget type="Button" skin="MW_Button" position="213 233 61 22" align="ALIGN_BOTTOM ALIGN_RIGHT" name="WorldButton"/> |         <Widget type="Button" skin="MW_Button" position="213 233 61 22" align="ALIGN_BOTTOM ALIGN_RIGHT" name="WorldButton"/> | ||||||
|  | 
 | ||||||
|     </Widget> |     </Widget> | ||||||
| </MyGUI> | </MyGUI> | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								files/mygui/openmw_map_window_skin.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								files/mygui/openmw_map_window_skin.xml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | 
 | ||||||
|  | <MyGUI type="Skin"> | ||||||
|  |     <Skin name="MW_MapView" size="516 516" texture="mwgui.png"> | ||||||
|  |         <Child type="Widget" skin="" offset="0 0 516 516" align="Stretch" name="Client"/> | ||||||
|  | 
 | ||||||
|  |         <!-- invisible scroll bars, needed for setting the view offset --> | ||||||
|  |         <Child type="ScrollBar" skin="" offset="498 3 14 509" align="ALIGN_RIGHT ALIGN_VSTRETCH" name="VScroll"/> | ||||||
|  |         <Child type="ScrollBar" skin="" offset="3 498 489 14" align="ALIGN_BOTTOM ALIGN_HSTRETCH" name="HScroll"/> | ||||||
|  |     </Skin> | ||||||
|  | </MyGUI> | ||||||
		Loading…
	
		Reference in a new issue