1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-21 18:40:01 +00:00

Track map position using MWWorld::Cell

This commit is contained in:
Evil Eye 2024-03-07 21:36:21 +01:00
parent 65d51665e5
commit b055367b3b
6 changed files with 63 additions and 66 deletions

View File

@ -202,9 +202,6 @@ namespace MWBase
virtual bool getFullHelp() const = 0; virtual bool getFullHelp() const = 0;
virtual void setActiveMap(int x, int y, bool interior) = 0;
///< set the indices of the map texture that should be used
/// sets the visibility of the drowning bar /// sets the visibility of the drowning bar
virtual void setDrowningBarVisibility(bool visible) = 0; virtual void setDrowningBarVisibility(bool visible) = 0;

View File

@ -95,6 +95,13 @@ namespace
return std::clamp( return std::clamp(
viewingDistanceInCells, Constants::CellGridRadius, Settings::map().mMaxLocalViewingDistance.get()); viewingDistanceInCells, Constants::CellGridRadius, Settings::map().mMaxLocalViewingDistance.get());
} }
ESM::RefId getCellIdInWorldSpace(const MWWorld::Cell* cell, int x, int y)
{
if (cell->isExterior())
return ESM::Cell::generateIdForCell(true, {}, x, y);
return cell->getId();
}
} }
namespace MWGui namespace MWGui
@ -170,12 +177,9 @@ namespace MWGui
LocalMapBase::LocalMapBase( LocalMapBase::LocalMapBase(
CustomMarkerCollection& markers, MWRender::LocalMap* localMapRender, bool fogOfWarEnabled) CustomMarkerCollection& markers, MWRender::LocalMap* localMapRender, bool fogOfWarEnabled)
: mLocalMapRender(localMapRender) : mLocalMapRender(localMapRender)
, mCurX(0) , mActiveCell(nullptr)
, mCurY(0)
, mInterior(false)
, mLocalMap(nullptr) , mLocalMap(nullptr)
, mCompass(nullptr) , mCompass(nullptr)
, mChanged(true)
, mFogOfWarToggled(true) , mFogOfWarToggled(true)
, mFogOfWarEnabled(fogOfWarEnabled) , mFogOfWarEnabled(fogOfWarEnabled)
, mNumCells(1) , mNumCells(1)
@ -231,12 +235,6 @@ namespace MWGui
} }
} }
void LocalMapBase::setCellPrefix(const std::string& prefix)
{
mPrefix = prefix;
mChanged = true;
}
bool LocalMapBase::toggleFogOfWar() bool LocalMapBase::toggleFogOfWar()
{ {
mFogOfWarToggled = !mFogOfWarToggled; mFogOfWarToggled = !mFogOfWarToggled;
@ -262,8 +260,9 @@ namespace MWGui
{ {
// normalized cell coordinates // normalized cell coordinates
auto mapWidgetSize = getWidgetSize(); auto mapWidgetSize = getWidgetSize();
return MyGUI::IntPoint(std::round(nX * mapWidgetSize + (mCellDistance + (cellX - mCurX)) * mapWidgetSize), return MyGUI::IntPoint(
std::round(nY * mapWidgetSize + (mCellDistance - (cellY - mCurY)) * mapWidgetSize)); std::round(nX * mapWidgetSize + (mCellDistance + (cellX - mActiveCell->getGridX())) * mapWidgetSize),
std::round(nY * mapWidgetSize + (mCellDistance - (cellY - mActiveCell->getGridY())) * mapWidgetSize));
} }
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos) const MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos) const
@ -272,7 +271,7 @@ namespace MWGui
// normalized cell coordinates // normalized cell coordinates
float nX, nY; float nX, nY;
if (!mInterior) if (mActiveCell->isExterior())
{ {
ESM::ExteriorCellLocation cellPos = ESM::positionToExteriorCellLocation(worldX, worldY); ESM::ExteriorCellLocation cellPos = ESM::positionToExteriorCellLocation(worldX, worldY);
cellIndex.x() = cellPos.mX; cellIndex.x() = cellPos.mX;
@ -336,7 +335,7 @@ namespace MWGui
std::vector<MyGUI::Widget*>& LocalMapBase::currentDoorMarkersWidgets() std::vector<MyGUI::Widget*>& LocalMapBase::currentDoorMarkersWidgets()
{ {
return mInterior ? mInteriorDoorMarkerWidgets : mExteriorDoorMarkerWidgets; return mActiveCell->isExterior() ? mExteriorDoorMarkerWidgets : mInteriorDoorMarkerWidgets;
} }
void LocalMapBase::updateCustomMarkers() void LocalMapBase::updateCustomMarkers()
@ -344,12 +343,14 @@ namespace MWGui
for (MyGUI::Widget* widget : mCustomMarkerWidgets) for (MyGUI::Widget* widget : mCustomMarkerWidgets)
MyGUI::Gui::getInstance().destroyWidget(widget); MyGUI::Gui::getInstance().destroyWidget(widget);
mCustomMarkerWidgets.clear(); mCustomMarkerWidgets.clear();
if (!mActiveCell)
return;
for (int dX = -mCellDistance; dX <= mCellDistance; ++dX) for (int dX = -mCellDistance; dX <= mCellDistance; ++dX)
{ {
for (int dY = -mCellDistance; dY <= mCellDistance; ++dY) for (int dY = -mCellDistance; dY <= mCellDistance; ++dY)
{ {
ESM::RefId cellRefId = ESM::Cell::generateIdForCell(!mInterior, mPrefix, mCurX + dX, mCurY + dY); ESM::RefId cellRefId
= getCellIdInWorldSpace(mActiveCell, mActiveCell->getGridX() + dX, mActiveCell->getGridY() + dY);
CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(cellRefId); CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(cellRefId);
for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second; for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second;
@ -377,16 +378,25 @@ namespace MWGui
redraw(); redraw();
} }
void LocalMapBase::setActiveCell(const int x, const int y, bool interior) void LocalMapBase::setActiveCell(const MWWorld::Cell& cell)
{ {
if (x == mCurX && y == mCurY && mInterior == interior && !mChanged) if (&cell == mActiveCell)
return; // don't do anything if we're still in the same cell return; // don't do anything if we're still in the same cell
if (!interior && !(x == mCurX && y == mCurY)) const int x = cell.getGridX();
const int y = cell.getGridY();
if (cell.isExterior())
{ {
const MyGUI::IntRect intersection int curX = 0;
= { std::max(x, mCurX) - mCellDistance, std::max(y, mCurY) - mCellDistance, int curY = 0;
std::min(x, mCurX) + mCellDistance, std::min(y, mCurY) + mCellDistance }; if (mActiveCell)
{
curX = mActiveCell->getGridX();
curY = mActiveCell->getGridY();
}
const MyGUI::IntRect intersection = { std::max(x, curX) - mCellDistance, std::max(y, curY) - mCellDistance,
std::min(x, curX) + mCellDistance, std::min(y, curY) + mCellDistance };
const MyGUI::IntRect activeGrid = createRect({ x, y }, Constants::CellGridRadius); const MyGUI::IntRect activeGrid = createRect({ x, y }, Constants::CellGridRadius);
const MyGUI::IntRect currentView = createRect({ x, y }, mCellDistance); const MyGUI::IntRect currentView = createRect({ x, y }, mCellDistance);
@ -407,17 +417,14 @@ namespace MWGui
for (auto& widget : mDoorMarkersToRecycle) for (auto& widget : mDoorMarkersToRecycle)
widget->setVisible(false); widget->setVisible(false);
for (auto const& cell : mMaps) for (auto const& entry : mMaps)
{ {
if (mHasALastActiveCell && !intersection.inside({ cell.mCellX, cell.mCellY })) if (mHasALastActiveCell && !intersection.inside({ entry.mCellX, entry.mCellY }))
mLocalMapRender->removeExteriorCell(cell.mCellX, cell.mCellY); mLocalMapRender->removeExteriorCell(entry.mCellX, entry.mCellY);
} }
} }
mCurX = x; mActiveCell = &cell;
mCurY = y;
mInterior = interior;
mChanged = false;
for (int mx = 0; mx < mNumCells; ++mx) for (int mx = 0; mx < mNumCells; ++mx)
{ {
@ -441,7 +448,7 @@ namespace MWGui
for (MyGUI::Widget* widget : currentDoorMarkersWidgets()) for (MyGUI::Widget* widget : currentDoorMarkersWidgets())
widget->setCoord(getMarkerCoordinates(widget, 8)); widget->setCoord(getMarkerCoordinates(widget, 8));
if (!mInterior) if (mActiveCell->isExterior())
mHasALastActiveCell = true; mHasALastActiveCell = true;
updateMagicMarkers(); updateMagicMarkers();
@ -580,7 +587,7 @@ namespace MWGui
if (!entry.mMapTexture) if (!entry.mMapTexture)
{ {
if (!mInterior) if (mActiveCell->isExterior())
requestMapRender(&MWBase::Environment::get().getWorldModel()->getExterior( requestMapRender(&MWBase::Environment::get().getWorldModel()->getExterior(
ESM::ExteriorCellLocation(entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId))); ESM::ExteriorCellLocation(entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId)));
@ -626,12 +633,12 @@ namespace MWGui
mDoorMarkersToRecycle.end(), mInteriorDoorMarkerWidgets.begin(), mInteriorDoorMarkerWidgets.end()); mDoorMarkersToRecycle.end(), mInteriorDoorMarkerWidgets.begin(), mInteriorDoorMarkerWidgets.end());
mInteriorDoorMarkerWidgets.clear(); mInteriorDoorMarkerWidgets.clear();
if (mInterior) if (!mActiveCell->isExterior())
{ {
for (MyGUI::Widget* widget : mExteriorDoorMarkerWidgets) for (MyGUI::Widget* widget : mExteriorDoorMarkerWidgets)
widget->setVisible(false); widget->setVisible(false);
MWWorld::CellStore& cell = worldModel->getInterior(mPrefix); MWWorld::CellStore& cell = worldModel->getInterior(mActiveCell->getNameId());
world->getDoorMarkers(cell, doors); world->getDoorMarkers(cell, doors);
} }
else else
@ -678,7 +685,7 @@ namespace MWGui
} }
currentDoorMarkersWidgets().push_back(markerWidget); currentDoorMarkersWidgets().push_back(markerWidget);
if (!mInterior) if (mActiveCell->isExterior())
mExteriorDoorsByCell[{ data->cellX, data->cellY }].push_back(markerWidget); mExteriorDoorsByCell[{ data->cellX, data->cellY }].push_back(markerWidget);
} }
@ -701,8 +708,7 @@ namespace MWGui
MWWorld::CellStore* markedCell = nullptr; MWWorld::CellStore* markedCell = nullptr;
ESM::Position markedPosition; ESM::Position markedPosition;
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition); MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
if (markedCell && markedCell->isExterior() == !mInterior if (markedCell && markedCell->getCell()->getWorldSpace() == mActiveCell->getWorldSpace())
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->getCell()->getNameId(), mPrefix)))
{ {
MarkerUserData markerPos(mLocalMapRender); MarkerUserData markerPos(mLocalMapRender);
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
@ -870,11 +876,11 @@ namespace MWGui
int y = (int(widgetPos.top / float(mapWidgetSize)) - mCellDistance) * -1; int y = (int(widgetPos.top / float(mapWidgetSize)) - mCellDistance) * -1;
float nX = widgetPos.left / float(mapWidgetSize) - int(widgetPos.left / float(mapWidgetSize)); float nX = widgetPos.left / float(mapWidgetSize) - int(widgetPos.left / float(mapWidgetSize));
float nY = widgetPos.top / float(mapWidgetSize) - int(widgetPos.top / float(mapWidgetSize)); float nY = widgetPos.top / float(mapWidgetSize) - int(widgetPos.top / float(mapWidgetSize));
x += mCurX; x += mActiveCell->getGridX();
y += mCurY; y += mActiveCell->getGridY();
osg::Vec2f worldPos; osg::Vec2f worldPos;
if (mInterior) if (!mActiveCell->isExterior())
{ {
worldPos = mLocalMapRender->interiorMapToWorldPosition(nX, nY, x, y); worldPos = mLocalMapRender->interiorMapToWorldPosition(nX, nY, x, y);
} }
@ -886,7 +892,7 @@ namespace MWGui
mEditingMarker.mWorldX = worldPos.x(); mEditingMarker.mWorldX = worldPos.x();
mEditingMarker.mWorldY = worldPos.y(); mEditingMarker.mWorldY = worldPos.y();
ESM::RefId clickedId = ESM::Cell::generateIdForCell(!mInterior, LocalMapBase::mPrefix, x, y); ESM::RefId clickedId = getCellIdInWorldSpace(mActiveCell, x, y);
mEditingMarker.mCell = clickedId; mEditingMarker.mCell = clickedId;
@ -977,7 +983,7 @@ namespace MWGui
resizeGlobalMap(); resizeGlobalMap();
float x = mCurPos.x(), y = mCurPos.y(); float x = mCurPos.x(), y = mCurPos.y();
if (mInterior) if (!mActiveCell->isExterior())
{ {
auto pos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition(); auto pos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
x = pos.x(); x = pos.x();
@ -1020,7 +1026,7 @@ namespace MWGui
resizeGlobalMap(); resizeGlobalMap();
} }
MapWindow::~MapWindow() {} MapWindow::~MapWindow() = default;
void MapWindow::setCellName(const std::string& cellName) void MapWindow::setCellName(const std::string& cellName)
{ {
@ -1289,7 +1295,7 @@ namespace MWGui
mMarkers.clear(); mMarkers.clear();
mGlobalMapRender->clear(); mGlobalMapRender->clear();
mChanged = true; mActiveCell = nullptr;
for (auto& widgetPair : mGlobalMapMarkers) for (auto& widgetPair : mGlobalMapMarkers)
MyGUI::Gui::getInstance().destroyWidget(widgetPair.first.widget); MyGUI::Gui::getInstance().destroyWidget(widgetPair.first.widget);

View File

@ -27,6 +27,7 @@ namespace ESM
namespace MWWorld namespace MWWorld
{ {
class Cell;
class CellStore; class CellStore;
} }
@ -77,8 +78,7 @@ namespace MWGui
virtual ~LocalMapBase(); virtual ~LocalMapBase();
void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, int cellDistance = Constants::CellGridRadius); void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, int cellDistance = Constants::CellGridRadius);
void setCellPrefix(const std::string& prefix); void setActiveCell(const MWWorld::Cell& cell);
void setActiveCell(const int x, const int y, bool interior = false);
void requestMapRender(const MWWorld::CellStore* cell); void requestMapRender(const MWWorld::CellStore* cell);
void setPlayerDir(const float x, const float y); void setPlayerDir(const float x, const float y);
void setPlayerPos(int cellX, int cellY, const float nx, const float ny); void setPlayerPos(int cellX, int cellY, const float nx, const float ny);
@ -115,15 +115,12 @@ namespace MWGui
float mLocalMapZoom = 1.f; float mLocalMapZoom = 1.f;
MWRender::LocalMap* mLocalMapRender; MWRender::LocalMap* mLocalMapRender;
int mCurX, mCurY; // the position of the active cell on the global map (in cell coords) const MWWorld::Cell* mActiveCell;
bool mHasALastActiveCell = false; bool mHasALastActiveCell = false;
osg::Vec2f mCurPos; // the position of the player in the world (in cell coords) osg::Vec2f mCurPos; // the position of the player in the world (in cell coords)
bool mInterior;
MyGUI::ScrollView* mLocalMap; MyGUI::ScrollView* mLocalMap;
MyGUI::ImageBox* mCompass; MyGUI::ImageBox* mCompass;
std::string mPrefix;
bool mChanged;
bool mFogOfWarToggled; bool mFogOfWarToggled;
bool mFogOfWarEnabled; bool mFogOfWarEnabled;

View File

@ -844,7 +844,7 @@ namespace MWGui
if (!player.getCell()->isExterior()) if (!player.getCell()->isExterior())
{ {
setActiveMap(x, y, true); setActiveMap(*player.getCell()->getCell());
} }
// else: need to know the current grid center, call setActiveMap from changeCell // else: need to know the current grid center, call setActiveMap from changeCell
@ -982,29 +982,23 @@ namespace MWGui
mMap->addVisitedLocation(name, cellCommon->getGridX(), cellCommon->getGridY()); mMap->addVisitedLocation(name, cellCommon->getGridX(), cellCommon->getGridY());
mMap->cellExplored(cellCommon->getGridX(), cellCommon->getGridY()); mMap->cellExplored(cellCommon->getGridX(), cellCommon->getGridY());
setActiveMap(cellCommon->getGridX(), cellCommon->getGridY(), false);
} }
else else
{ {
mMap->setCellPrefix(std::string(cellCommon->getNameId()));
mHud->setCellPrefix(std::string(cellCommon->getNameId()));
osg::Vec3f worldPos; osg::Vec3f worldPos;
if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos)) if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos))
worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition(); worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
else else
MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos); MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos);
mMap->setGlobalMapPlayerPosition(worldPos.x(), worldPos.y()); mMap->setGlobalMapPlayerPosition(worldPos.x(), worldPos.y());
setActiveMap(0, 0, true);
} }
setActiveMap(*cellCommon);
} }
void WindowManager::setActiveMap(int x, int y, bool interior) void WindowManager::setActiveMap(const MWWorld::Cell& cell)
{ {
mMap->setActiveCell(x, y, interior); mMap->setActiveCell(cell);
mHud->setActiveCell(x, y, interior); mHud->setActiveCell(cell);
} }
void WindowManager::setDrowningBarVisibility(bool visible) void WindowManager::setDrowningBarVisibility(bool visible)

View File

@ -50,6 +50,7 @@ namespace MyGUI
namespace MWWorld namespace MWWorld
{ {
class Cell;
class ESMStore; class ESMStore;
} }
@ -216,9 +217,6 @@ namespace MWGui
bool toggleFullHelp() override; ///< show extra info in item tooltips (owner, script) bool toggleFullHelp() override; ///< show extra info in item tooltips (owner, script)
bool getFullHelp() const override; bool getFullHelp() const override;
void setActiveMap(int x, int y, bool interior) override;
///< set the indices of the map texture that should be used
/// sets the visibility of the drowning bar /// sets the visibility of the drowning bar
void setDrowningBarVisibility(bool visible) override; void setDrowningBarVisibility(bool visible) override;
@ -589,6 +587,9 @@ namespace MWGui
void setCullMask(uint32_t mask) override; void setCullMask(uint32_t mask) override;
uint32_t getCullMask() override; uint32_t getCullMask() override;
void setActiveMap(const MWWorld::Cell& cell);
///< set the indices of the map texture that should be used
Files::ConfigurationManager& mCfgMgr; Files::ConfigurationManager& mCfgMgr;
}; };
} }

View File

@ -100,6 +100,8 @@ namespace MWWorld
mWaterHeight = -1.f; mWaterHeight = -1.f;
mHasWater = true; mHasWater = true;
} }
else
mGridPos = {};
} }
ESM::RefId Cell::getWorldSpace() const ESM::RefId Cell::getWorldSpace() const