forked from teamnwah/openmw-tes3coop
Merge remote branch 'scrawl/minimap' into next
This commit is contained in:
commit
9ec1e55aaf
19 changed files with 831 additions and 26 deletions
|
@ -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");
|
||||
MapWindow();
|
||||
|
||||
// Obviously you should override this later on
|
||||
setCellName("No Cell Loaded");
|
||||
}
|
||||
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);
|
||||
|
||||
void setCellName(const std::string& cellName)
|
||||
{
|
||||
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(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.
|
||||
|
|
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:
|
||||
// - 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);
|
||||
|
||||
|
@ -103,6 +107,9 @@ class RenderingManager: private RenderingInterface {
|
|||
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>
|
||||
|
|
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