mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-24 04:11:50 -04:00
Merge branch 'localmap' into 'master'
Local map fixes See merge request OpenMW/openmw!4919
This commit is contained in:
commit
4d5b65a9cb
@ -635,7 +635,6 @@ namespace MWGui
|
|||||||
mSpellBox->setUserData(MyGUI::Any::Null);
|
mSpellBox->setUserData(MyGUI::Any::Null);
|
||||||
|
|
||||||
mActiveCell = nullptr;
|
mActiveCell = nullptr;
|
||||||
mHasALastActiveCell = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::customMarkerCreated(MyGUI::Widget* marker)
|
void HUD::customMarkerCreated(MyGUI::Widget* marker)
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
const int cellSize = Constants::CellSizeInUnits;
|
constexpr int cellSize = Constants::CellSizeInUnits;
|
||||||
constexpr float speed = 1.08f; // the zoom speed, it should be greater than 1
|
constexpr float speed = 1.08f; // the zoom speed, it should be greater than 1
|
||||||
|
|
||||||
enum LocalMapWidgetDepth
|
enum LocalMapWidgetDepth
|
||||||
@ -57,7 +57,10 @@ namespace
|
|||||||
Global_ExploreOverlayLayer = 2,
|
Global_ExploreOverlayLayer = 2,
|
||||||
Global_MapLayer = 3
|
Global_MapLayer = 3
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
/// @brief A widget that changes its color when hovered.
|
/// @brief A widget that changes its color when hovered.
|
||||||
class MarkerWidget final : public MyGUI::Widget
|
class MarkerWidget final : public MyGUI::Widget
|
||||||
{
|
{
|
||||||
@ -108,10 +111,6 @@ namespace
|
|||||||
{
|
{
|
||||||
scrollView->setCanvasSize(widgetSize * (grid.width() + 1), widgetSize * (grid.height() + 1));
|
scrollView->setCanvasSize(widgetSize * (grid.width() + 1), widgetSize * (grid.height() + 1));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
namespace MWGui
|
|
||||||
{
|
|
||||||
|
|
||||||
void CustomMarkerCollection::addMarker(const ESM::CustomMarker& marker, bool triggerEvent)
|
void CustomMarkerCollection::addMarker(const ESM::CustomMarker& marker, bool triggerEvent)
|
||||||
{
|
{
|
||||||
@ -217,7 +216,6 @@ namespace MWGui
|
|||||||
mLocalMap = widget;
|
mLocalMap = widget;
|
||||||
mCompass = compass;
|
mCompass = compass;
|
||||||
mGrid = createRect({ 0, 0 }, cellDistance);
|
mGrid = createRect({ 0, 0 }, cellDistance);
|
||||||
mExtCellDistance = cellDistance;
|
|
||||||
|
|
||||||
const int mapWidgetSize = Settings::map().mLocalMapWidgetSize;
|
const int mapWidgetSize = Settings::map().mLocalMapWidgetSize;
|
||||||
setCanvasSize(mLocalMap, mGrid, mapWidgetSize);
|
setCanvasSize(mLocalMap, mGrid, mapWidgetSize);
|
||||||
@ -293,7 +291,7 @@ namespace MWGui
|
|||||||
return MyGUI::IntCoord(position.left - halfMarkerSize, position.top - halfMarkerSize, markerSize, markerSize);
|
return MyGUI::IntCoord(position.left - halfMarkerSize, position.top - halfMarkerSize, markerSize, markerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::Widget* LocalMapBase::createDoorMarker(const std::string& name, float x, float y) const
|
MarkerWidget* LocalMapBase::createDoorMarker(const std::string& name, float x, float y) const
|
||||||
{
|
{
|
||||||
MarkerUserData data(mLocalMapRender);
|
MarkerUserData data(mLocalMapRender);
|
||||||
data.caption = name;
|
data.caption = name;
|
||||||
@ -320,14 +318,15 @@ namespace MWGui
|
|||||||
mLocalMap->setViewOffset(viewOffset);
|
mLocalMap->setViewOffset(viewOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntCoord LocalMapBase::getMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const
|
void LocalMapBase::updateMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const
|
||||||
{
|
{
|
||||||
MarkerUserData& markerPos(*widget->getUserData<MarkerUserData>());
|
MarkerUserData& markerPos(*widget->getUserData<MarkerUserData>());
|
||||||
auto position = getPosition(markerPos.cellX, markerPos.cellY, markerPos.nX, markerPos.nY);
|
auto position = getPosition(markerPos.cellX, markerPos.cellY, markerPos.nX, markerPos.nY);
|
||||||
return MyGUI::IntCoord(position.left - markerSize / 2, position.top - markerSize / 2, markerSize, markerSize);
|
MyGUI::IntCoord coord(position.left - markerSize / 2, position.top - markerSize / 2, markerSize, markerSize);
|
||||||
|
widget->setCoord(coord);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MyGUI::Widget*>& LocalMapBase::currentDoorMarkersWidgets()
|
std::vector<MarkerWidget*>& LocalMapBase::currentDoorMarkersWidgets()
|
||||||
{
|
{
|
||||||
return mActiveCell->isExterior() ? mExteriorDoorMarkerWidgets : mInteriorDoorMarkerWidgets;
|
return mActiveCell->isExterior() ? mExteriorDoorMarkerWidgets : mInteriorDoorMarkerWidgets;
|
||||||
}
|
}
|
||||||
@ -380,43 +379,73 @@ namespace MWGui
|
|||||||
if (&cell == mActiveCell)
|
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
|
||||||
|
|
||||||
|
// Remove all interior door markers
|
||||||
|
mDoorMarkersToRecycle.insert(
|
||||||
|
mDoorMarkersToRecycle.end(), mInteriorDoorMarkerWidgets.begin(), mInteriorDoorMarkerWidgets.end());
|
||||||
|
for (MarkerWidget* widget : mInteriorDoorMarkerWidgets)
|
||||||
|
widget->setVisible(false);
|
||||||
|
mInteriorDoorMarkerWidgets.clear();
|
||||||
|
|
||||||
const int x = cell.getGridX();
|
const int x = cell.getGridX();
|
||||||
const int y = cell.getGridY();
|
const int y = cell.getGridY();
|
||||||
|
|
||||||
MyGUI::IntSize oldSize{ mGrid.width(), mGrid.height() };
|
const MyGUI::IntRect prevGrid = mGrid;
|
||||||
|
|
||||||
if (cell.isExterior())
|
if (cell.isExterior())
|
||||||
{
|
{
|
||||||
mGrid = createRect({ x, y }, mExtCellDistance);
|
std::optional<MyGUI::IntRect> previousActiveGrid;
|
||||||
|
if (mActiveCell && mActiveCell->isExterior())
|
||||||
|
previousActiveGrid
|
||||||
|
= createRect({ mActiveCell->getGridX(), mActiveCell->getGridY() }, Constants::CellGridRadius);
|
||||||
|
mGrid = createRect({ x, y }, getLocalViewingDistance());
|
||||||
const MyGUI::IntRect activeGrid = createRect({ x, y }, Constants::CellGridRadius);
|
const MyGUI::IntRect activeGrid = createRect({ x, y }, Constants::CellGridRadius);
|
||||||
|
|
||||||
mExteriorDoorMarkerWidgets.clear();
|
mExteriorDoorMarkerWidgets.clear();
|
||||||
for (auto& [coord, doors] : mExteriorDoorsByCell)
|
for (auto it = mExteriorDoorsByCell.begin(); it != mExteriorDoorsByCell.end();)
|
||||||
{
|
{
|
||||||
if (!mHasALastActiveCell || !mGrid.inside({ coord.first, coord.second })
|
const auto& [coord, doors] = *it;
|
||||||
|| activeGrid.inside({ coord.first, coord.second }))
|
const MyGUI::IntPoint pos(coord.first, coord.second);
|
||||||
|
// Remove markers that fall outside the rendered map and ones that are new to the active grid.
|
||||||
|
// Scripts can enable/disable doors, requiring us to update the markers. Morrowind.exe only updates
|
||||||
|
// markers when a cell is added to the active grid.
|
||||||
|
if (!mGrid.inside(pos)
|
||||||
|
|| (previousActiveGrid && !previousActiveGrid->inside(pos) && activeGrid.inside(pos)))
|
||||||
{
|
{
|
||||||
mDoorMarkersToRecycle.insert(mDoorMarkersToRecycle.end(), doors.begin(), doors.end());
|
mDoorMarkersToRecycle.insert(mDoorMarkersToRecycle.end(), doors.begin(), doors.end());
|
||||||
doors.clear();
|
for (MarkerWidget* widget : doors)
|
||||||
}
|
|
||||||
else
|
|
||||||
mExteriorDoorMarkerWidgets.insert(mExteriorDoorMarkerWidgets.end(), doors.begin(), doors.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& widget : mDoorMarkersToRecycle)
|
|
||||||
widget->setVisible(false);
|
widget->setVisible(false);
|
||||||
|
it = mExteriorDoorsByCell.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mExteriorDoorMarkerWidgets.insert(mExteriorDoorMarkerWidgets.end(), doors.begin(), doors.end());
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mHasALastActiveCell)
|
if (mActiveCell && mActiveCell->isExterior())
|
||||||
{
|
{
|
||||||
for (const auto& entry : mMaps)
|
for (int cx = prevGrid.left; cx <= prevGrid.right; ++cx)
|
||||||
{
|
{
|
||||||
if (!mGrid.inside({ entry.mCellX, entry.mCellY }))
|
for (int cy = prevGrid.top; cy <= prevGrid.bottom; ++cy)
|
||||||
mLocalMapRender->removeExteriorCell(entry.mCellX, entry.mCellY);
|
{
|
||||||
|
if (!mGrid.inside({ cx, cy }))
|
||||||
|
mLocalMapRender->removeExteriorCell(cx, cy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
mGrid = mLocalMapRender->getInteriorGrid();
|
mGrid = mLocalMapRender->getInteriorGrid();
|
||||||
|
// Remove all exterior door markers
|
||||||
|
mDoorMarkersToRecycle.insert(
|
||||||
|
mDoorMarkersToRecycle.end(), mExteriorDoorMarkerWidgets.begin(), mExteriorDoorMarkerWidgets.end());
|
||||||
|
for (MarkerWidget* widget : mExteriorDoorMarkerWidgets)
|
||||||
|
widget->setVisible(false);
|
||||||
|
mExteriorDoorMarkerWidgets.clear();
|
||||||
|
mExteriorDoorsByCell.clear();
|
||||||
|
}
|
||||||
|
|
||||||
mActiveCell = &cell;
|
mActiveCell = &cell;
|
||||||
|
|
||||||
@ -452,18 +481,15 @@ namespace MWGui
|
|||||||
resetEntry(mMaps[i], false, nullptr);
|
resetEntry(mMaps[i], false, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldSize != MyGUI::IntSize{ mGrid.width(), mGrid.height() })
|
if (prevGrid.width() != mGrid.width() || prevGrid.height() != mGrid.height())
|
||||||
setCanvasSize(mLocalMap, mGrid, getWidgetSize());
|
updateLocalMap();
|
||||||
|
|
||||||
// Delay the door markers update until scripts have been given a chance to run.
|
// Delay the door markers update until scripts have been given a chance to run.
|
||||||
// If we don't do this, door markers that should be disabled will still appear on the map.
|
// If we don't do this, door markers that should be disabled will still appear on the map.
|
||||||
mNeedDoorMarkersUpdate = true;
|
mNeedDoorMarkersUpdate = true;
|
||||||
|
|
||||||
for (MyGUI::Widget* widget : currentDoorMarkersWidgets())
|
for (MyGUI::Widget* widget : currentDoorMarkersWidgets())
|
||||||
widget->setCoord(getMarkerCoordinates(widget, 8));
|
updateMarkerCoordinates(widget, 8);
|
||||||
|
|
||||||
if (mActiveCell->isExterior())
|
|
||||||
mHasALastActiveCell = true;
|
|
||||||
|
|
||||||
updateMagicMarkers();
|
updateMagicMarkers();
|
||||||
updateCustomMarkers();
|
updateCustomMarkers();
|
||||||
@ -588,7 +614,7 @@ namespace MWGui
|
|||||||
bool needRedraw = false;
|
bool needRedraw = false;
|
||||||
for (MapEntry& entry : mMaps)
|
for (MapEntry& entry : mMaps)
|
||||||
{
|
{
|
||||||
if (widgetCropped(entry.mMapWidget, mLocalMap))
|
if (!entry.mMapWidget->getVisible() || widgetCropped(entry.mMapWidget, mLocalMap))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!entry.mMapTexture)
|
if (!entry.mMapTexture)
|
||||||
@ -623,6 +649,9 @@ namespace MWGui
|
|||||||
entry.mFogTexture = std::make_unique<MyGUIPlatform::OSGTexture>(std::string(), nullptr);
|
entry.mFogTexture = std::make_unique<MyGUIPlatform::OSGTexture>(std::string(), nullptr);
|
||||||
}
|
}
|
||||||
needRedraw = true;
|
needRedraw = true;
|
||||||
|
// Newly uncovered chunk, make sure to draw door markers right away instead of waiting for a cell
|
||||||
|
// transition
|
||||||
|
mNeedDoorMarkersUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needRedraw)
|
if (needRedraw)
|
||||||
@ -635,15 +664,8 @@ namespace MWGui
|
|||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
MWWorld::WorldModel* worldModel = MWBase::Environment::get().getWorldModel();
|
MWWorld::WorldModel* worldModel = MWBase::Environment::get().getWorldModel();
|
||||||
|
|
||||||
mDoorMarkersToRecycle.insert(
|
|
||||||
mDoorMarkersToRecycle.end(), mInteriorDoorMarkerWidgets.begin(), mInteriorDoorMarkerWidgets.end());
|
|
||||||
mInteriorDoorMarkerWidgets.clear();
|
|
||||||
|
|
||||||
if (!mActiveCell->isExterior())
|
if (!mActiveCell->isExterior())
|
||||||
{
|
{
|
||||||
for (MyGUI::Widget* widget : mExteriorDoorMarkerWidgets)
|
|
||||||
widget->setVisible(false);
|
|
||||||
|
|
||||||
MWWorld::CellStore& cell = worldModel->getInterior(mActiveCell->getNameId());
|
MWWorld::CellStore& cell = worldModel->getInterior(mActiveCell->getNameId());
|
||||||
world->getDoorMarkers(cell, doors);
|
world->getDoorMarkers(cell, doors);
|
||||||
}
|
}
|
||||||
@ -651,13 +673,13 @@ namespace MWGui
|
|||||||
{
|
{
|
||||||
for (MapEntry& entry : mMaps)
|
for (MapEntry& entry : mMaps)
|
||||||
{
|
{
|
||||||
if (!entry.mMapTexture && !widgetCropped(entry.mMapWidget, mLocalMap))
|
if (!entry.mMapWidget->getVisible() || widgetCropped(entry.mMapWidget, mLocalMap))
|
||||||
world->getDoorMarkers(worldModel->getExterior(ESM::ExteriorCellLocation(
|
continue;
|
||||||
entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId)),
|
if (mExteriorDoorsByCell.contains({ entry.mCellX, entry.mCellY }))
|
||||||
doors);
|
continue;
|
||||||
|
ESM::ExteriorCellLocation id(entry.mCellX, entry.mCellY, ESM::Cell::sDefaultWorldspaceId);
|
||||||
|
world->getDoorMarkers(worldModel->getExterior(id), doors);
|
||||||
}
|
}
|
||||||
if (doors.empty())
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a widget for each marker
|
// Create a widget for each marker
|
||||||
@ -665,11 +687,10 @@ namespace MWGui
|
|||||||
{
|
{
|
||||||
std::vector<std::string> destNotes;
|
std::vector<std::string> destNotes;
|
||||||
CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(marker.dest);
|
CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(marker.dest);
|
||||||
for (CustomMarkerCollection::ContainerType::const_iterator iter = markers.first; iter != markers.second;
|
for (auto iter = markers.first; iter != markers.second; ++iter)
|
||||||
++iter)
|
|
||||||
destNotes.push_back(iter->second.mNote);
|
destNotes.push_back(iter->second.mNote);
|
||||||
|
|
||||||
MyGUI::Widget* markerWidget = nullptr;
|
MarkerWidget* markerWidget = nullptr;
|
||||||
MarkerUserData* data;
|
MarkerUserData* data;
|
||||||
if (mDoorMarkersToRecycle.empty())
|
if (mDoorMarkersToRecycle.empty())
|
||||||
{
|
{
|
||||||
@ -680,7 +701,7 @@ namespace MWGui
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
markerWidget = (MarkerWidget*)mDoorMarkersToRecycle.back();
|
markerWidget = mDoorMarkersToRecycle.back();
|
||||||
mDoorMarkersToRecycle.pop_back();
|
mDoorMarkersToRecycle.pop_back();
|
||||||
|
|
||||||
data = markerWidget->getUserData<MarkerUserData>();
|
data = markerWidget->getUserData<MarkerUserData>();
|
||||||
@ -695,8 +716,8 @@ namespace MWGui
|
|||||||
mExteriorDoorsByCell[{ data->cellX, data->cellY }].push_back(markerWidget);
|
mExteriorDoorsByCell[{ data->cellX, data->cellY }].push_back(markerWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& widget : mDoorMarkersToRecycle)
|
for (MyGUI::Widget* widget : currentDoorMarkersWidgets())
|
||||||
widget->setVisible(false);
|
updateMarkerCoordinates(widget, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalMapBase::updateMagicMarkers()
|
void LocalMapBase::updateMagicMarkers()
|
||||||
@ -738,6 +759,8 @@ namespace MWGui
|
|||||||
const auto size = MyGUI::IntSize(std::ceil(mapWidgetSize), std::ceil(mapWidgetSize));
|
const auto size = MyGUI::IntSize(std::ceil(mapWidgetSize), std::ceil(mapWidgetSize));
|
||||||
for (auto& entry : mMaps)
|
for (auto& entry : mMaps)
|
||||||
{
|
{
|
||||||
|
if (!entry.mMapWidget->getVisible())
|
||||||
|
continue;
|
||||||
const auto position = getPosition(entry.mCellX, entry.mCellY, 0, 0);
|
const auto position = getPosition(entry.mCellX, entry.mCellY, 0, 0);
|
||||||
entry.mMapWidget->setCoord({ position, size });
|
entry.mMapWidget->setCoord({ position, size });
|
||||||
entry.mFogWidget->setCoord({ position, size });
|
entry.mFogWidget->setCoord({ position, size });
|
||||||
@ -745,7 +768,7 @@ namespace MWGui
|
|||||||
|
|
||||||
MarkerUserData markerPos(mLocalMapRender);
|
MarkerUserData markerPos(mLocalMapRender);
|
||||||
for (MyGUI::Widget* widget : currentDoorMarkersWidgets())
|
for (MyGUI::Widget* widget : currentDoorMarkersWidgets())
|
||||||
widget->setCoord(getMarkerCoordinates(widget, 8));
|
updateMarkerCoordinates(widget, 8);
|
||||||
|
|
||||||
for (MyGUI::Widget* widget : mCustomMarkerWidgets)
|
for (MyGUI::Widget* widget : mCustomMarkerWidgets)
|
||||||
{
|
{
|
||||||
@ -754,7 +777,7 @@ namespace MWGui
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (MyGUI::Widget* widget : mMagicMarkerWidgets)
|
for (MyGUI::Widget* widget : mMagicMarkerWidgets)
|
||||||
widget->setCoord(getMarkerCoordinates(widget, 8));
|
updateMarkerCoordinates(widget, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
@ -1368,8 +1391,7 @@ namespace MWGui
|
|||||||
NoDrop::setAlpha(alpha);
|
NoDrop::setAlpha(alpha);
|
||||||
// can't allow showing map with partial transparency, as the fog of war will also go transparent
|
// can't allow showing map with partial transparency, as the fog of war will also go transparent
|
||||||
// and reveal parts of the map you shouldn't be able to see
|
// and reveal parts of the map you shouldn't be able to see
|
||||||
for (MapEntry& entry : mMaps)
|
mLocalMap->setVisible(alpha == 1);
|
||||||
entry.mMapWidget->setVisible(alpha == 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::customMarkerCreated(MyGUI::Widget* marker)
|
void MapWindow::customMarkerCreated(MyGUI::Widget* marker)
|
||||||
|
@ -43,6 +43,7 @@ namespace SceneUtil
|
|||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
class MarkerWidget;
|
||||||
|
|
||||||
class CustomMarkerCollection
|
class CustomMarkerCollection
|
||||||
{
|
{
|
||||||
@ -119,7 +120,6 @@ namespace MWGui
|
|||||||
MyGUI::ScrollView* mLocalMap = nullptr;
|
MyGUI::ScrollView* mLocalMap = nullptr;
|
||||||
MyGUI::ImageBox* mCompass = nullptr;
|
MyGUI::ImageBox* mCompass = nullptr;
|
||||||
float mLocalMapZoom = 1.f;
|
float mLocalMapZoom = 1.f;
|
||||||
bool mHasALastActiveCell = false;
|
|
||||||
bool mFogOfWarToggled = true;
|
bool mFogOfWarToggled = true;
|
||||||
bool mFogOfWarEnabled;
|
bool mFogOfWarEnabled;
|
||||||
bool mNeedDoorMarkersUpdate = false;
|
bool mNeedDoorMarkersUpdate = false;
|
||||||
@ -147,14 +147,14 @@ namespace MWGui
|
|||||||
std::vector<MapEntry> mMaps;
|
std::vector<MapEntry> mMaps;
|
||||||
|
|
||||||
// Keep track of created marker widgets, just to easily remove them later.
|
// Keep track of created marker widgets, just to easily remove them later.
|
||||||
std::vector<MyGUI::Widget*> mExteriorDoorMarkerWidgets;
|
std::vector<MarkerWidget*> mExteriorDoorMarkerWidgets;
|
||||||
std::map<std::pair<int, int>, std::vector<MyGUI::Widget*>> mExteriorDoorsByCell;
|
std::map<std::pair<int, int>, std::vector<MarkerWidget*>> mExteriorDoorsByCell;
|
||||||
std::vector<MyGUI::Widget*> mInteriorDoorMarkerWidgets;
|
std::vector<MarkerWidget*> mInteriorDoorMarkerWidgets;
|
||||||
std::vector<MyGUI::Widget*> mMagicMarkerWidgets;
|
std::vector<MyGUI::Widget*> mMagicMarkerWidgets;
|
||||||
std::vector<MyGUI::Widget*> mCustomMarkerWidgets;
|
std::vector<MyGUI::Widget*> mCustomMarkerWidgets;
|
||||||
std::vector<MyGUI::Widget*> mDoorMarkersToRecycle;
|
std::vector<MarkerWidget*> mDoorMarkersToRecycle;
|
||||||
|
|
||||||
std::vector<MyGUI::Widget*>& currentDoorMarkersWidgets();
|
std::vector<MarkerWidget*>& currentDoorMarkersWidgets();
|
||||||
|
|
||||||
virtual void updateCustomMarkers();
|
virtual void updateCustomMarkers();
|
||||||
|
|
||||||
@ -164,12 +164,11 @@ namespace MWGui
|
|||||||
MyGUI::IntPoint getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos) const;
|
MyGUI::IntPoint getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos) const;
|
||||||
MyGUI::IntCoord getMarkerCoordinates(
|
MyGUI::IntCoord getMarkerCoordinates(
|
||||||
float worldX, float worldY, MarkerUserData& markerPos, size_t markerSize) const;
|
float worldX, float worldY, MarkerUserData& markerPos, size_t markerSize) const;
|
||||||
MyGUI::Widget* createDoorMarker(const std::string& name, float x, float y) const;
|
MarkerWidget* createDoorMarker(const std::string& name, float x, float y) const;
|
||||||
MyGUI::IntCoord getMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const;
|
void updateMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const;
|
||||||
|
|
||||||
virtual void notifyPlayerUpdate() {}
|
virtual void notifyPlayerUpdate() {}
|
||||||
virtual void centerView();
|
virtual void centerView();
|
||||||
virtual void notifyMapChanged() {}
|
|
||||||
|
|
||||||
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
|
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
|
||||||
virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
|
virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
|
||||||
@ -185,7 +184,6 @@ namespace MWGui
|
|||||||
MWGui::LocalMapBase::MapEntry& addMapEntry();
|
MWGui::LocalMapBase::MapEntry& addMapEntry();
|
||||||
|
|
||||||
MyGUI::IntRect mGrid{ -1, -1, 1, 1 };
|
MyGUI::IntRect mGrid{ -1, -1, 1, 1 };
|
||||||
int mExtCellDistance = 0;
|
|
||||||
float mMarkerUpdateTimer = 0.f;
|
float mMarkerUpdateTimer = 0.f;
|
||||||
|
|
||||||
float mLastDirectionX = 0.f;
|
float mLastDirectionX = 0.f;
|
||||||
|
@ -96,7 +96,7 @@ namespace MWRender
|
|||||||
mRoot->removeChild(rtt);
|
mRoot->removeChild(rtt);
|
||||||
}
|
}
|
||||||
|
|
||||||
const osg::Vec2f LocalMap::rotatePoint(const osg::Vec2f& point, const osg::Vec2f& center, const float angle)
|
const osg::Vec2f LocalMap::rotatePoint(const osg::Vec2f& point, const osg::Vec2f& center, const float angle) const
|
||||||
{
|
{
|
||||||
return osg::Vec2f(
|
return osg::Vec2f(
|
||||||
std::cos(angle) * (point.x() - center.x()) - std::sin(angle) * (point.y() - center.y()) + center.x(),
|
std::cos(angle) * (point.x() - center.x()) - std::sin(angle) * (point.y() - center.y()) + center.x(),
|
||||||
@ -109,12 +109,15 @@ namespace MWRender
|
|||||||
mInteriorSegments.clear();
|
mInteriorSegments.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalMap::saveFogOfWar(MWWorld::CellStore* cell)
|
void LocalMap::saveFogOfWar(MWWorld::CellStore* cell) const
|
||||||
{
|
{
|
||||||
if (!mInterior)
|
if (!mInterior)
|
||||||
{
|
{
|
||||||
const MapSegment& segment
|
const auto it
|
||||||
= mExteriorSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())];
|
= mExteriorSegments.find(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
|
||||||
|
if (it == mExteriorSegments.end())
|
||||||
|
return;
|
||||||
|
const MapSegment& segment = it->second;
|
||||||
|
|
||||||
if (segment.mFogOfWarImage && segment.mHasFogState)
|
if (segment.mFogOfWarImage && segment.mHasFogState)
|
||||||
{
|
{
|
||||||
@ -146,7 +149,10 @@ namespace MWRender
|
|||||||
{
|
{
|
||||||
for (int y = 0; y < segments.second; ++y)
|
for (int y = 0; y < segments.second; ++y)
|
||||||
{
|
{
|
||||||
const MapSegment& segment = mInteriorSegments[std::make_pair(x, y)];
|
const auto it = mInteriorSegments.find(std::make_pair(x, y));
|
||||||
|
if (it == mInteriorSegments.end())
|
||||||
|
continue;
|
||||||
|
const MapSegment& segment = it->second;
|
||||||
if (!segment.mHasFogState)
|
if (!segment.mHasFogState)
|
||||||
continue;
|
continue;
|
||||||
ESM::FogTexture& texture = fog->mFogTextures.emplace_back();
|
ESM::FogTexture& texture = fog->mFogTextures.emplace_back();
|
||||||
@ -186,7 +192,8 @@ namespace MWRender
|
|||||||
|
|
||||||
MapSegment& segment = mExteriorSegments[std::make_pair(cellX, cellY)];
|
MapSegment& segment = mExteriorSegments[std::make_pair(cellX, cellY)];
|
||||||
const std::uint8_t neighbourFlags = getExteriorNeighbourFlags(cellX, cellY);
|
const std::uint8_t neighbourFlags = getExteriorNeighbourFlags(cellX, cellY);
|
||||||
if ((segment.mLastRenderNeighbourFlags & neighbourFlags) == neighbourFlags)
|
if (segment.mLastRenderNeighbourFlags != 0
|
||||||
|
&& (segment.mLastRenderNeighbourFlags & neighbourFlags) == neighbourFlags)
|
||||||
return;
|
return;
|
||||||
requestExteriorMap(cell, segment);
|
requestExteriorMap(cell, segment);
|
||||||
segment.mLastRenderNeighbourFlags = neighbourFlags;
|
segment.mLastRenderNeighbourFlags = neighbourFlags;
|
||||||
@ -208,9 +215,7 @@ namespace MWRender
|
|||||||
{
|
{
|
||||||
saveFogOfWar(cell);
|
saveFogOfWar(cell);
|
||||||
|
|
||||||
if (cell->isExterior())
|
if (!cell->isExterior())
|
||||||
mExteriorSegments.erase({ cell->getCell()->getGridX(), cell->getCell()->getGridY() });
|
|
||||||
else
|
|
||||||
mInteriorSegments.clear();
|
mInteriorSegments.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,6 +304,7 @@ namespace MWRender
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
mInterior = true;
|
mInterior = true;
|
||||||
|
mExteriorSegments.clear();
|
||||||
|
|
||||||
mBounds = bounds;
|
mBounds = bounds;
|
||||||
|
|
||||||
@ -422,7 +428,7 @@ namespace MWRender
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalMap::worldToInteriorMapPosition(osg::Vec2f pos, float& nX, float& nY, int& x, int& y)
|
void LocalMap::worldToInteriorMapPosition(osg::Vec2f pos, float& nX, float& nY, int& x, int& y) const
|
||||||
{
|
{
|
||||||
pos = rotatePoint(pos, mCenter, mAngle);
|
pos = rotatePoint(pos, mCenter, mAngle);
|
||||||
|
|
||||||
@ -435,7 +441,7 @@ namespace MWRender
|
|||||||
nY = 1.0f - (pos.y() - min.y() - mMapWorldSize * y) / mMapWorldSize;
|
nY = 1.0f - (pos.y() - min.y() - mMapWorldSize * y) / mMapWorldSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec2f LocalMap::interiorMapToWorldPosition(float nX, float nY, int x, int y)
|
osg::Vec2f LocalMap::interiorMapToWorldPosition(float nX, float nY, int x, int y) const
|
||||||
{
|
{
|
||||||
osg::Vec2f min(mBounds.xMin(), mBounds.yMin());
|
osg::Vec2f min(mBounds.xMin(), mBounds.yMin());
|
||||||
osg::Vec2f pos(mMapWorldSize * (nX + x) + min.x(), mMapWorldSize * (1.0f - nY + y) + min.y());
|
osg::Vec2f pos(mMapWorldSize * (nX + x) + min.x(), mMapWorldSize * (1.0f - nY + y) + min.y());
|
||||||
@ -571,8 +577,11 @@ namespace MWRender
|
|||||||
};
|
};
|
||||||
std::uint8_t result = 0;
|
std::uint8_t result = 0;
|
||||||
for (const auto& [flag, dx, dy] : flags)
|
for (const auto& [flag, dx, dy] : flags)
|
||||||
if (mExteriorSegments.contains(std::pair(cellX + dx, cellY + dy)))
|
{
|
||||||
|
auto it = mExteriorSegments.find(std::pair(cellX + dx, cellY + dy));
|
||||||
|
if (it != mExteriorSegments.end() && it->second.mMapTexture)
|
||||||
result |= flag;
|
result |= flag;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,14 +83,14 @@ namespace MWRender
|
|||||||
* Save the fog of war for this cell to its CellStore.
|
* Save the fog of war for this cell to its CellStore.
|
||||||
* @remarks This should be called when unloading a cell, and for all active cells prior to saving the game.
|
* @remarks This should be called when unloading a cell, and for all active cells prior to saving the game.
|
||||||
*/
|
*/
|
||||||
void saveFogOfWar(MWWorld::CellStore* cell);
|
void saveFogOfWar(MWWorld::CellStore* cell) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the interior map texture index and normalized position on this texture, given a world position
|
* Get the interior map texture index and normalized position on this texture, given a world position
|
||||||
*/
|
*/
|
||||||
void worldToInteriorMapPosition(osg::Vec2f pos, float& nX, float& nY, int& x, int& y);
|
void worldToInteriorMapPosition(osg::Vec2f pos, float& nX, float& nY, int& x, int& y) const;
|
||||||
|
|
||||||
osg::Vec2f interiorMapToWorldPosition(float nX, float nY, int x, int y);
|
osg::Vec2f interiorMapToWorldPosition(float nX, float nY, int x, int y) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a given position is explored by the player (i.e. not obscured by fog of war)
|
* Check if a given position is explored by the player (i.e. not obscured by fog of war)
|
||||||
@ -149,7 +149,7 @@ namespace MWRender
|
|||||||
int mCellDistance;
|
int mCellDistance;
|
||||||
|
|
||||||
float mAngle;
|
float mAngle;
|
||||||
const osg::Vec2f rotatePoint(const osg::Vec2f& point, const osg::Vec2f& center, const float angle);
|
const osg::Vec2f rotatePoint(const osg::Vec2f& point, const osg::Vec2f& center, const float angle) const;
|
||||||
|
|
||||||
void requestExteriorMap(const MWWorld::CellStore* cell, MapSegment& segment);
|
void requestExteriorMap(const MWWorld::CellStore* cell, MapSegment& segment);
|
||||||
void requestInteriorMap(const MWWorld::CellStore* cell);
|
void requestInteriorMap(const MWWorld::CellStore* cell);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user