forked from teamnwah/openmw-tes3coop
door markers on the local map
This commit is contained in:
parent
34c30b132c
commit
5834b4baa5
13 changed files with 260 additions and 22 deletions
|
@ -65,6 +65,12 @@ namespace MWBase
|
|||
Render_Compositors
|
||||
};
|
||||
|
||||
struct DoorMarker
|
||||
{
|
||||
std::string name;
|
||||
float x, y; // world position
|
||||
};
|
||||
|
||||
World() {}
|
||||
|
||||
virtual ~World() {}
|
||||
|
@ -108,6 +114,15 @@ namespace MWBase
|
|||
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||
///< get north vector (OGRE coordinates) for given interior cell
|
||||
|
||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell) = 0;
|
||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
|
||||
///< see MWRender::LocalMap::getInteriorMapPosition
|
||||
|
||||
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior) = 0;
|
||||
///< see MWRender::LocalMap::isPositionExplored
|
||||
|
||||
virtual MWWorld::Globals::Data& getGlobalVariable (const std::string& name) = 0;
|
||||
|
||||
virtual MWWorld::Globals::Data getGlobalVariable (const std::string& name) const = 0;
|
||||
|
|
|
@ -60,7 +60,6 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
|
|||
getWidget(mHealth, "Health");
|
||||
getWidget(mMagicka, "Magicka");
|
||||
getWidget(mStamina, "Stamina");
|
||||
|
||||
mHealthManaStaminaBaseLeft = mHealthFrame->getLeft();
|
||||
|
||||
MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame;
|
||||
|
@ -93,9 +92,10 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
|
|||
|
||||
getWidget(mMinimapBox, "MiniMapBox");
|
||||
mMinimapBoxBaseRight = viewSize.width - mMinimapBox->getRight();
|
||||
mMinimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
||||
getWidget(mMinimap, "MiniMap");
|
||||
getWidget(mCompass, "Compass");
|
||||
getWidget(mMinimapButton, "MiniMapButton");
|
||||
mMinimapButton->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
||||
|
||||
getWidget(mCellNameBox, "CellName");
|
||||
getWidget(mWeaponSpellBox, "WeaponSpellName");
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace MWGui
|
|||
MyGUI::ImageBox *mWeapImage, *mSpellImage;
|
||||
MyGUI::ProgressPtr mWeapStatus, mSpellStatus;
|
||||
MyGUI::Widget *mEffectBox, *mMinimapBox;
|
||||
MyGUI::Button* mMinimapButton;
|
||||
MyGUI::ImageBox* mEffect1;
|
||||
MyGUI::ScrollView* mMinimap;
|
||||
MyGUI::ImageBox* mCompass;
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
#include "map_window.hpp"
|
||||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <OgreVector2.h>
|
||||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
LocalMapBase::LocalMapBase()
|
||||
|
@ -92,10 +96,21 @@ void LocalMapBase::applyFogOfWar()
|
|||
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
|
||||
|
||||
// clear all previous markers
|
||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||
{
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||
{
|
||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
{
|
||||
// map
|
||||
std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(x + (mx-1)) + "_"
|
||||
+ boost::lexical_cast<std::string>(y + (interior ? (my-1) : -1*(my-1)));
|
||||
|
||||
|
@ -108,12 +123,79 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
|
|||
box->setImageTexture(image);
|
||||
else
|
||||
box->setImageTexture("black.png");
|
||||
|
||||
|
||||
// door markers
|
||||
|
||||
// interior map only consists of one cell, so handle the markers only once
|
||||
if (interior && (mx != 2 || my != 2))
|
||||
continue;
|
||||
|
||||
MWWorld::CellStore* cell;
|
||||
if (interior)
|
||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
||||
else
|
||||
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
|
||||
|
||||
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
|
||||
|
||||
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
||||
{
|
||||
MWBase::World::DoorMarker marker = *it;
|
||||
|
||||
// convert world coordinates to normalized cell coordinates
|
||||
MyGUI::IntCoord widgetCoord;
|
||||
float nX,nY;
|
||||
int cellDx, cellDy;
|
||||
if (!interior)
|
||||
{
|
||||
const int cellSize = 8192;
|
||||
|
||||
nX = (marker.x - cellSize * (x+mx-1)) / cellSize;
|
||||
nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize;
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 3 + mx * 512, nY * 512 - 3 + my * 512, 7, 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::Vector2 position (marker.x, -marker.y);
|
||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy);
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 3 + (1+cellDx-x) * 512, nY * 512 - 3 + (1+cellDy-y) * 512, 7, 7);
|
||||
}
|
||||
|
||||
std::cout << "widgetCoord " << widgetCoord.left << " " << widgetCoord.top << " nX " << nX << " nY " << nY << " xy " << x << " " << y << std::endl;
|
||||
|
||||
static int counter = 0;
|
||||
++counter;
|
||||
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageTexture ("textures\\door_icon.dds");
|
||||
markerWidget->setImageCoord (MyGUI::IntCoord(0,0,7,7));
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTip");
|
||||
markerWidget->setUserString("Caption_Text", marker.name);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
|
||||
MarkerPosition markerPos;
|
||||
markerPos.interior = interior;
|
||||
markerPos.cellX = interior ? cellDx : x + mx - 1;
|
||||
markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1);
|
||||
markerPos.nX = nX;
|
||||
markerPos.nY = nY;
|
||||
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
mInterior = interior;
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mChanged = false;
|
||||
|
||||
// fog of war
|
||||
applyFogOfWar();
|
||||
|
||||
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
|
||||
|
|
|
@ -18,6 +18,15 @@ namespace MWGui
|
|||
|
||||
void toggleFogOfWar();
|
||||
|
||||
struct MarkerPosition
|
||||
{
|
||||
bool interior;
|
||||
int cellX;
|
||||
int cellY;
|
||||
float nX;
|
||||
float nY;
|
||||
};
|
||||
|
||||
protected:
|
||||
int mCurX, mCurY;
|
||||
bool mInterior;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "map_window.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
@ -150,7 +151,19 @@ void ToolTips::onFrame(float frameDuration)
|
|||
{
|
||||
return;
|
||||
}
|
||||
else if (type == "ItemPtr")
|
||||
|
||||
// special handling for markers on the local map: the tooltip should only be visible
|
||||
// if the marker is not hidden due to the fog of war.
|
||||
if (focus->getUserString ("IsMarker") == "true")
|
||||
{
|
||||
LocalMapBase::MarkerPosition pos = *focus->getUserData<LocalMapBase::MarkerPosition>();
|
||||
|
||||
if (!MWBase::Environment::get().getWorld ()->isPositionExplored (pos.nX, pos.nY, pos.cellX, pos.cellY, pos.interior))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (type == "ItemPtr")
|
||||
{
|
||||
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
|
||||
tooltipSize = getToolTipViaPtr(false);
|
||||
|
@ -199,7 +212,8 @@ void ToolTips::onFrame(float frameDuration)
|
|||
it != userStrings.end(); ++it)
|
||||
{
|
||||
if (it->first == "ToolTipType"
|
||||
|| it->first == "ToolTipLayout")
|
||||
|| it->first == "ToolTipLayout"
|
||||
|| it->first == "IsMarker")
|
||||
continue;
|
||||
|
||||
|
||||
|
|
|
@ -270,6 +270,34 @@ void LocalMap::render(const float x, const float y,
|
|||
mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd);
|
||||
}
|
||||
|
||||
void LocalMap::getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y)
|
||||
{
|
||||
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().z), mAngle);
|
||||
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
|
||||
|
||||
x = std::ceil((pos.x - min.x)/sSize)-1;
|
||||
y = std::ceil((pos.y - min.y)/sSize)-1;
|
||||
|
||||
nX = (pos.x - min.x - sSize*x)/sSize;
|
||||
nY = (pos.y - min.y - sSize*y)/sSize;
|
||||
}
|
||||
|
||||
bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interior)
|
||||
{
|
||||
std::string texName = (interior ? mInteriorName + "_" : "Cell_") + coordStr(x, y);
|
||||
|
||||
if (mBuffers.find(texName) == mBuffers.end())
|
||||
return false;
|
||||
|
||||
int texU = (sFogOfWarResolution-1) * nX;
|
||||
int texV = (sFogOfWarResolution-1) * nY;
|
||||
|
||||
Ogre::uint32 clr = mBuffers[texName][texV * sFogOfWarResolution + texU];
|
||||
uint8 alpha = (clr >> 24);
|
||||
return alpha < 200;
|
||||
}
|
||||
|
||||
void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
|
||||
{
|
||||
if (sFogOfWarSkip != 0)
|
||||
|
@ -281,14 +309,12 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
|||
|
||||
// retrieve the x,y grid coordinates the player is in
|
||||
int x,y;
|
||||
Vector3 _pos(position.x, 0, position.z);
|
||||
Vector2 pos(_pos.x, _pos.z);
|
||||
float u,v;
|
||||
|
||||
Vector2 pos(position.x, position.z);
|
||||
|
||||
if (mInterior)
|
||||
{
|
||||
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().z), mAngle);
|
||||
}
|
||||
|
||||
getInteriorMapPosition(pos, u,v, x,y);
|
||||
|
||||
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis();
|
||||
|
||||
|
@ -303,14 +329,10 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
|||
}
|
||||
else
|
||||
{
|
||||
x = std::ceil((pos.x - min.x)/sSize)-1;
|
||||
y = std::ceil((pos.y - min.y)/sSize)-1;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setInteriorMapTexture(x,y);
|
||||
}
|
||||
|
||||
// convert from world coordinates to texture UV coordinates
|
||||
float u,v;
|
||||
std::string texBaseName;
|
||||
if (!mInterior)
|
||||
{
|
||||
|
@ -320,9 +342,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
|||
}
|
||||
else
|
||||
{
|
||||
u = (pos.x - min.x - sSize*x)/sSize;
|
||||
v = (pos.y - min.y - sSize*y)/sSize;
|
||||
|
||||
texBaseName = mInteriorName + "_";
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,18 @@ namespace MWRender
|
|||
*/
|
||||
void saveFogOfWar(MWWorld::CellStore* cell);
|
||||
|
||||
|
||||
/**
|
||||
* Get the interior map texture index and normalized position
|
||||
* on this texture, given a world position (in ogre coordinates)
|
||||
*/
|
||||
void getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y);
|
||||
|
||||
/**
|
||||
* Check if a given position is explored by the player (i.e. not obscured by fog of war)
|
||||
*/
|
||||
bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
|
||||
|
||||
private:
|
||||
OEngine::Render::OgreRenderer* mRendering;
|
||||
MWRender::RenderingManager* mRenderingManager;
|
||||
|
|
|
@ -863,4 +863,14 @@ void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float
|
|||
mPlayer->getSightAngles(pitch, yaw);
|
||||
}
|
||||
|
||||
void RenderingManager::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y)
|
||||
{
|
||||
return mLocalMap->getInteriorMapPosition (position, nX, nY, x, y);
|
||||
}
|
||||
|
||||
bool RenderingManager::isPositionExplored (float nX, float nY, int x, int y, bool interior)
|
||||
{
|
||||
return mLocalMap->isPositionExplored(nX, nY, x, y, interior);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -184,6 +184,12 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
|
|||
|
||||
static bool waterShaderSupported();
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y);
|
||||
///< see MWRender::LocalMap::getInteriorMapPosition
|
||||
|
||||
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
|
||||
///< see MWRender::LocalMap::isPositionExplored
|
||||
|
||||
protected:
|
||||
virtual void windowResized(Ogre::RenderWindow* rw);
|
||||
virtual void windowClosed(Ogre::RenderWindow* rw);
|
||||
|
|
|
@ -1031,6 +1031,64 @@ namespace MWWorld
|
|||
return d;
|
||||
}
|
||||
|
||||
std::vector<World::DoorMarker> World::getDoorMarkers (CellStore* cell)
|
||||
{
|
||||
std::vector<World::DoorMarker> result;
|
||||
|
||||
MWWorld::CellRefList<ESM::Door> doors = cell->doors;
|
||||
std::list< MWWorld::LiveCellRef<ESM::Door> > refList = doors.list;
|
||||
for (std::list< MWWorld::LiveCellRef<ESM::Door> >::iterator it = refList.begin(); it != refList.end(); ++it)
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Door> ref = *it;
|
||||
|
||||
if (ref.ref.teleport)
|
||||
{
|
||||
World::DoorMarker newMarker;
|
||||
|
||||
std::string dest;
|
||||
if (ref.ref.destCell != "")
|
||||
{
|
||||
// door leads to an interior, use interior name
|
||||
dest = ref.ref.destCell;
|
||||
}
|
||||
else
|
||||
{
|
||||
// door leads to exterior, use cell name (if any), otherwise translated region name
|
||||
int x,y;
|
||||
positionToIndex (ref.ref.doorDest.pos[0], ref.ref.doorDest.pos[1], x, y);
|
||||
const ESM::Cell* cell = mStore.cells.findExt(x,y);
|
||||
if (cell->name != "")
|
||||
dest = cell->name;
|
||||
else
|
||||
{
|
||||
const ESM::Region* region = mStore.regions.search(cell->region);
|
||||
dest = region->name;
|
||||
}
|
||||
}
|
||||
|
||||
newMarker.name = dest;
|
||||
|
||||
ESM::Position pos = ref.mData.getPosition ();
|
||||
|
||||
newMarker.x = pos.pos[0];
|
||||
newMarker.y = pos.pos[1];
|
||||
result.push_back(newMarker);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void World::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y)
|
||||
{
|
||||
mRendering->getInteriorMapPosition(position, nX, nY, x, y);
|
||||
}
|
||||
|
||||
bool World::isPositionExplored (float nX, float nY, int x, int y, bool interior)
|
||||
{
|
||||
return mRendering->isPositionExplored(nX, nY, x, y, interior);
|
||||
}
|
||||
|
||||
void World::setWaterHeight(const float height)
|
||||
{
|
||||
mRendering->setWaterHeight(height);
|
||||
|
|
|
@ -140,6 +140,15 @@ namespace MWWorld
|
|||
virtual Ogre::Vector2 getNorthVector (CellStore* cell);
|
||||
///< get north vector (OGRE coordinates) for given interior cell
|
||||
|
||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell);
|
||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y);
|
||||
///< see MWRender::LocalMap::getInteriorMapPosition
|
||||
|
||||
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
|
||||
///< see MWRender::LocalMap::isPositionExplored
|
||||
|
||||
virtual Globals::Data& getGlobalVariable (const std::string& name);
|
||||
|
||||
virtual Globals::Data getGlobalVariable (const std::string& name) const;
|
||||
|
|
|
@ -76,18 +76,21 @@
|
|||
</Widget>
|
||||
|
||||
<!-- Map box -->
|
||||
<Widget type="Button" skin="" position="223 123 65 65" name="MiniMapBox" align="Right Bottom">
|
||||
<Widget type="Widget" skin="" position="223 123 65 65" name="MiniMapBox" align="Right Bottom">
|
||||
<Widget type="Widget" skin="HUD_Box" position="0 0 65 65" align="Center">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
|
||||
<Widget type="ScrollView" skin="MW_MapView" position="2 2 61 61" align="Left Bottom" name="MiniMap">
|
||||
<Property key="NeedMouse" value="false"/>
|
||||
<Property key="CanvasSize" value="1536 1536"/>
|
||||
|
||||
<Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="ALIGN_BOTTOM ALIGN_LEFT" name="Compass">
|
||||
<Property key="ImageTexture" value="textures\compass.dds"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="Button" skin="" position="0 0 1536 1536" name="MiniMapButton" align="Right Bottom">
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
|
Loading…
Reference in a new issue