Merge remote branch 'scrawl/minimap' into next

actorid
Marc Zinnschlag 13 years ago
commit 9ec1e55aaf

@ -14,7 +14,8 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderinginterface
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
renderinginterface localmap
)
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");
setSpellStatus(65, 100);
setEffect("icons\\s\\tx_s_chameleon.dds");
LocalMapBase::init(minimap, this);
}
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 "window_base.hpp"
#include <cmath>
/*
This file contains classes corresponding to window layouts
defined in resources/mygui/ *.xml.
@ -29,7 +31,25 @@
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:
HUD(int width, int height, int fpsLevel);
@ -43,13 +63,15 @@ namespace MWGui
void setFPS(float fps);
void setTriangleCount(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::ImageBox *weapImage, *spellImage;
MyGUI::ProgressPtr weapStatus, spellStatus;
MyGUI::WidgetPtr effectBox;
MyGUI::ImageBox* effect1;
MyGUI::ImageBox* minimap;
MyGUI::ScrollView* minimap;
MyGUI::ImageBox* compass;
MyGUI::ImageBox* crosshair;
@ -59,24 +81,27 @@ namespace MWGui
MyGUI::TextBox* batchcounter;
};
class MapWindow : public OEngine::GUI::Layout
class MapWindow : public OEngine::GUI::Layout, public LocalMapBase
{
public:
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
setCellName("No Cell Loaded");
}
void setCellName(const std::string& cellName)
{
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(cellName);
}
MapWindow();
void setVisible(bool b);
void setPlayerPos(const float x, const float y);
void setPlayerDir(const float x, const float y);
void setCellName(const std::string& cellName);
private:
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
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

@ -400,3 +400,47 @@ const ESMS::ESMStore& WindowManager::getStore() const
{
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/gui/manager.hpp>
#include "../mwmechanics/stat.hpp"
#include "../mwworld/ptr.hpp"
#include "mode.hpp"
namespace MyGUI
@ -152,6 +153,12 @@ namespace MWGui
void setBounty (int bounty); ///< set the current bounty value
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>
void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr.

@ -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();
}
}

@ -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:
// - there will be too many batches.
sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500));
mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL;
mBounds[ptr.getCell()].merge(ent->getBoundingBox());
}
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());
mBounds[ptr.getCell()].merge(insert->_getDerivedPosition());
mRenderer.getScene()->destroyEntity(ent);
}
@ -202,6 +206,9 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store)
mRenderer.getScene()->destroyStaticGeometry (sg);
sg = 0;
}
if(mBounds.find(store) != mBounds.end())
mBounds.erase(store);
}
void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
@ -212,3 +219,8 @@ void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
sg->build();
}
}
Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
{
return mBounds[cell];
}

@ -14,6 +14,7 @@ class Objects{
OEngine::Render::OgreRenderer &mRenderer;
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
std::map<MWWorld::Ptr::CellStore *, Ogre::AxisAlignedBox> mBounds;
Ogre::SceneNode* mMwRoot;
bool mIsStatic;
static int uniqueID;
@ -42,6 +43,9 @@ public:
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
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);
///< \return found?

@ -55,6 +55,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
mSun = 0;
mLocalMap = new MWRender::LocalMap(&mRendering, &environment);
}
RenderingManager::~RenderingManager ()
@ -62,6 +64,7 @@ RenderingManager::~RenderingManager ()
//TODO: destroy mSun?
delete mPlayer;
delete mSkyManager;
delete mLocalMap;
}
MWRender::SkyManager* RenderingManager::getSkyManager()
@ -137,6 +140,8 @@ void RenderingManager::update (float duration){
mSkyManager->update(duration);
mRendering.update(duration);
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() );
}
void RenderingManager::skyEnable ()
@ -327,4 +332,17 @@ void RenderingManager::setGlare(bool 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

@ -24,6 +24,7 @@
#include "objects.hpp"
#include "actors.hpp"
#include "player.hpp"
#include "localmap.hpp"
namespace Ogre
{
@ -75,6 +76,9 @@ class RenderingManager: private RenderingInterface {
/// when rebatching is needed and update automatically at the end of each frame.
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 removeObject (const MWWorld::Ptr& ptr);
@ -102,6 +106,9 @@ class RenderingManager: private RenderingInterface {
int skyGetSecundaPhase() const;
void skySetMoonColour (bool red);
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
void configureFog(ESMS::CellStore<MWWorld::RefData> &mCell);
@ -148,6 +155,8 @@ class RenderingManager: private RenderingInterface {
MWRender::Player *mPlayer;
MWRender::Debugging mDebugging;
MWRender::LocalMap* mLocalMap;
};
}

@ -6,6 +6,8 @@
#include "../mwsound/soundmanager.hpp"
#include "../mwgui/window_manager.hpp"
#include "ptr.hpp"
#include "environment.hpp"
#include "player.hpp"
@ -101,7 +103,8 @@ namespace MWWorld
insertCell(*cell, mEnvironment);
mRendering.cellAdded (cell);
mRendering.configureAmbient(*cell);
mRendering.requestMap(cell);
mRendering.configureAmbient(*cell);
}
@ -117,10 +120,14 @@ namespace MWWorld
// TODO orientation
mEnvironment.mMechanicsManager->addActor (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)
{
mRendering.preCellChange(mCurrentCell);
// remove active
mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer());

@ -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_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_skin.xml" "${DDIR}/openmw_map_window_skin.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_stats_window_layout.xml" "${DDIR}/openmw_stats_window_layout.xml" COPYONLY)

@ -14,4 +14,7 @@
<BasisSkin type="MainSkin" offset = "0 0 16 16"/>
</Skin>
<Skin name = "RotatingSkin" size = "16 16">
<BasisSkin type="RotatingSkin" offset="0 0 16 16" align="Stretch"/>
</Skin>
</MyGUI>

@ -20,6 +20,7 @@
<List file="openmw_mainmenu_skin.xml" group="General"/>
<List file="openmw_console.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_settings.xml" group="General"/>
</MyGUI>

@ -38,10 +38,48 @@
<!-- Map box -->
<Widget type="Widget" skin="HUD_Box" position="223 123 65 65"
align="Right Bottom">
<Widget type="ImageBox" skin="ImageBox" position="2 2 61 61" align="Left Bottom"
name="MiniMap"/>
<Widget type="ImageBox" skin="ImageBox" position="17 18 32 32" align="Left Bottom"
name="Compass"/>
<Widget type="ScrollView" skin="MW_MapView" position="2 2 61 61" align="Left Bottom" name="MiniMap">
<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">
<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>
<!-- Crosshair -->

@ -197,7 +197,7 @@
<Child type="ScrollBar" skin="MW_VScroll" offset = "498 3 14 509" align = "ALIGN_RIGHT ALIGN_VSTRETCH" name = "VScroll">
</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 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" />
<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 type="Widget" skin="IB_T" offset="2 0 512 2" align="ALIGN_TOP ALIGN_HSTRETCH"/>

@ -2,8 +2,60 @@
<MyGUI type="Layout">
<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>
</MyGUI>

@ -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…
Cancel
Save