mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 03:15:32 +00:00
Merge pull request #2286 from akortunov/map
Do not re-render maps for all active cells during cell transitions
This commit is contained in:
commit
216f908a07
9 changed files with 122 additions and 89 deletions
|
@ -351,6 +351,7 @@ namespace MWBase
|
|||
virtual std::string correctTexturePath(const std::string& path) = 0;
|
||||
virtual bool textureExists(const std::string& path) = 0;
|
||||
|
||||
virtual void addCell(MWWorld::CellStore* cell) = 0;
|
||||
virtual void removeCell(MWWorld::CellStore* cell) = 0;
|
||||
virtual void writeFog(MWWorld::CellStore* cell) = 0;
|
||||
|
||||
|
|
|
@ -237,9 +237,6 @@ namespace MWGui
|
|||
{
|
||||
for (int my=0; my<mNumCells; ++my)
|
||||
{
|
||||
int x = mCurX + (mx - mCellDistance);
|
||||
int y = mCurY + (-1*(my - mCellDistance));
|
||||
|
||||
MapEntry& entry = mMaps[my + mNumCells*mx];
|
||||
MyGUI::ImageBox* fog = entry.mFogWidget;
|
||||
|
||||
|
@ -249,19 +246,6 @@ namespace MWGui
|
|||
entry.mFogTexture.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> tex = mLocalMapRender->getFogOfWarTexture(x, y);
|
||||
if (tex)
|
||||
{
|
||||
entry.mFogTexture.reset(new osgMyGUI::OSGTexture(tex));
|
||||
fog->setRenderItemTexture(entry.mFogTexture.get());
|
||||
fog->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
fog->setImageTexture("black");
|
||||
entry.mFogTexture.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,31 +350,18 @@ namespace MWGui
|
|||
mInterior = interior;
|
||||
mChanged = false;
|
||||
|
||||
applyFogOfWar();
|
||||
|
||||
// Update the map textures
|
||||
for (int mx=0; mx<mNumCells; ++mx)
|
||||
{
|
||||
for (int my=0; my<mNumCells; ++my)
|
||||
{
|
||||
int mapX = x + (mx - mCellDistance);
|
||||
int mapY = y + (-1*(my - mCellDistance));
|
||||
|
||||
MapEntry& entry = mMaps[my + mNumCells*mx];
|
||||
MyGUI::ImageBox* box = entry.mMapWidget;
|
||||
entry.mMapWidget->setRenderItemTexture(nullptr);
|
||||
entry.mFogWidget->setRenderItemTexture(nullptr);
|
||||
entry.mMapTexture.reset();
|
||||
entry.mFogTexture.reset();
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(mapX, mapY);
|
||||
if (texture)
|
||||
{
|
||||
entry.mMapTexture.reset(new osgMyGUI::OSGTexture(texture));
|
||||
box->setRenderItemTexture(entry.mMapTexture.get());
|
||||
box->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
box->setRenderItemTexture(nullptr);
|
||||
entry.mMapTexture.reset();
|
||||
}
|
||||
entry.mCellX = x + (mx - mCellDistance);
|
||||
entry.mCellY = y - (my - mCellDistance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,22 +375,7 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell)
|
||||
{
|
||||
std::set<const MWWorld::CellStore*> cells;
|
||||
if (!cell->isExterior())
|
||||
cells.insert(cell);
|
||||
else
|
||||
{
|
||||
for (int dX=-mCellDistance; dX<=mCellDistance; ++dX)
|
||||
{
|
||||
for (int dY=-mCellDistance; dY<=mCellDistance; ++dY)
|
||||
{
|
||||
const MWWorld::CellStore* gridCell = MWBase::Environment::get().getWorld()->getExterior (cell->getCell()->getGridX()+dX, cell->getCell()->getGridY()+dY);
|
||||
cells.insert(gridCell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLocalMapRender->requestMap(cells);
|
||||
mLocalMapRender->requestMap(cell);
|
||||
}
|
||||
|
||||
void LocalMapBase::redraw()
|
||||
|
@ -522,6 +478,68 @@ namespace MWGui
|
|||
mMarkerUpdateTimer = 0;
|
||||
updateMagicMarkers();
|
||||
}
|
||||
|
||||
updateRequiredMaps();
|
||||
}
|
||||
|
||||
bool widgetCropped(MyGUI::Widget* widget, MyGUI::Widget* cropTo)
|
||||
{
|
||||
MyGUI::IntRect coord = widget->getAbsoluteRect();
|
||||
MyGUI::IntRect croppedCoord = cropTo->getAbsoluteRect();
|
||||
if (coord.left < croppedCoord.left && coord.right < croppedCoord.left)
|
||||
return true;
|
||||
if (coord.left > croppedCoord.right && coord.right > croppedCoord.right)
|
||||
return true;
|
||||
if (coord.top < croppedCoord.top && coord.bottom < croppedCoord.top)
|
||||
return true;
|
||||
if (coord.top > croppedCoord.bottom && coord.bottom > croppedCoord.bottom)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void LocalMapBase::updateRequiredMaps()
|
||||
{
|
||||
bool needRedraw = false;
|
||||
for (MapEntry& entry : mMaps)
|
||||
{
|
||||
if (widgetCropped(entry.mMapWidget, mLocalMap))
|
||||
continue;
|
||||
|
||||
if (!entry.mMapTexture)
|
||||
{
|
||||
if (!mInterior)
|
||||
requestMapRender(MWBase::Environment::get().getWorld()->getExterior (entry.mCellX, entry.mCellY));
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(entry.mCellX, entry.mCellY);
|
||||
if (texture)
|
||||
{
|
||||
entry.mMapTexture.reset(new osgMyGUI::OSGTexture(texture));
|
||||
entry.mMapWidget->setRenderItemTexture(entry.mMapTexture.get());
|
||||
entry.mMapWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
|
||||
needRedraw = true;
|
||||
}
|
||||
else
|
||||
entry.mMapTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
|
||||
}
|
||||
if (!entry.mFogTexture && mFogOfWarToggled && mFogOfWarEnabled)
|
||||
{
|
||||
osg::ref_ptr<osg::Texture2D> tex = mLocalMapRender->getFogOfWarTexture(entry.mCellX, entry.mCellY);
|
||||
if (tex)
|
||||
{
|
||||
entry.mFogTexture.reset(new osgMyGUI::OSGTexture(tex));
|
||||
entry.mFogWidget->setRenderItemTexture(entry.mFogTexture.get());
|
||||
entry.mFogWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.mFogWidget->setImageTexture("black");
|
||||
entry.mFogTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
|
||||
}
|
||||
needRedraw = true;
|
||||
}
|
||||
}
|
||||
if (needRedraw)
|
||||
redraw();
|
||||
}
|
||||
|
||||
void LocalMapBase::updateDoorMarkers()
|
||||
|
|
|
@ -129,12 +129,14 @@ namespace MWGui
|
|||
struct MapEntry
|
||||
{
|
||||
MapEntry(MyGUI::ImageBox* mapWidget, MyGUI::ImageBox* fogWidget)
|
||||
: mMapWidget(mapWidget), mFogWidget(fogWidget) {}
|
||||
: mMapWidget(mapWidget), mFogWidget(fogWidget), mCellX(0), mCellY(0) {}
|
||||
|
||||
MyGUI::ImageBox* mMapWidget;
|
||||
MyGUI::ImageBox* mFogWidget;
|
||||
std::shared_ptr<MyGUI::ITexture> mMapTexture;
|
||||
std::shared_ptr<MyGUI::ITexture> mFogTexture;
|
||||
int mCellX;
|
||||
int mCellY;
|
||||
};
|
||||
std::vector<MapEntry> mMaps;
|
||||
|
||||
|
@ -155,6 +157,8 @@ namespace MWGui
|
|||
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
|
||||
virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
|
||||
|
||||
void updateRequiredMaps();
|
||||
|
||||
void updateMagicMarkers();
|
||||
void addDetectionMarkers(int type);
|
||||
|
||||
|
|
|
@ -976,6 +976,12 @@ namespace MWGui
|
|||
|
||||
void WindowManager::onFrame (float frameDuration)
|
||||
{
|
||||
bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!=
|
||||
MWBase::StateManager::State_NoGame;
|
||||
|
||||
if (gameRunning)
|
||||
updateMap();
|
||||
|
||||
if (!mGuiModes.empty())
|
||||
{
|
||||
GuiModeState& state = mGuiModeStates[mGuiModes.back()];
|
||||
|
@ -1019,14 +1025,11 @@ namespace MWGui
|
|||
if (mLocalMapRender)
|
||||
mLocalMapRender->cleanupCameras();
|
||||
|
||||
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||
MWBase::StateManager::State_NoGame)
|
||||
if (!gameRunning)
|
||||
return;
|
||||
|
||||
mDragAndDrop->onFrame();
|
||||
|
||||
updateMap();
|
||||
|
||||
mHud->onFrame(frameDuration);
|
||||
|
||||
mDebugWindow->onFrame(frameDuration);
|
||||
|
@ -2232,6 +2235,11 @@ namespace MWGui
|
|||
tex->unlock();
|
||||
}
|
||||
|
||||
void WindowManager::addCell(MWWorld::CellStore* cell)
|
||||
{
|
||||
mLocalMapRender->addCell(cell);
|
||||
}
|
||||
|
||||
void WindowManager::removeCell(MWWorld::CellStore *cell)
|
||||
{
|
||||
mLocalMapRender->removeCell(cell);
|
||||
|
|
|
@ -379,6 +379,7 @@ namespace MWGui
|
|||
virtual std::string correctTexturePath(const std::string& path);
|
||||
virtual bool textureExists(const std::string& path);
|
||||
|
||||
void addCell(MWWorld::CellStore* cell);
|
||||
void removeCell(MWWorld::CellStore* cell);
|
||||
void writeFog(MWWorld::CellStore* cell);
|
||||
|
||||
|
|
|
@ -256,36 +256,30 @@ bool needUpdate(std::set<std::pair<int, int> >& renderedGrid, std::set<std::pair
|
|||
return false;
|
||||
}
|
||||
|
||||
void LocalMap::requestMap(std::set<const MWWorld::CellStore*> cells)
|
||||
void LocalMap::requestMap(const MWWorld::CellStore* cell)
|
||||
{
|
||||
std::set<std::pair<int, int> > grid;
|
||||
for (const MWWorld::CellStore* cell : cells)
|
||||
if (cell->isExterior())
|
||||
{
|
||||
if (cell->isExterior())
|
||||
grid.insert(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
|
||||
}
|
||||
int cellX = cell->getCell()->getGridX();
|
||||
int cellY = cell->getCell()->getGridY();
|
||||
|
||||
for (const MWWorld::CellStore* cell : cells)
|
||||
{
|
||||
if (cell->isExterior())
|
||||
{
|
||||
int cellX = cell->getCell()->getGridX();
|
||||
int cellY = cell->getCell()->getGridY();
|
||||
|
||||
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
|
||||
if (!needUpdate(segment.mGrid, grid, cellX, cellY))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
segment.mGrid = grid;
|
||||
requestExteriorMap(cell);
|
||||
}
|
||||
}
|
||||
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
|
||||
if (!needUpdate(segment.mGrid, mCurrentGrid, cellX, cellY))
|
||||
return;
|
||||
else
|
||||
requestInteriorMap(cell);
|
||||
{
|
||||
segment.mGrid = mCurrentGrid;
|
||||
requestExteriorMap(cell);
|
||||
}
|
||||
}
|
||||
else
|
||||
requestInteriorMap(cell);
|
||||
}
|
||||
|
||||
void LocalMap::addCell(MWWorld::CellStore *cell)
|
||||
{
|
||||
if (cell->isExterior())
|
||||
mCurrentGrid.emplace(cell->getCell()->getGridX(), cell->getCell()->getGridY());
|
||||
}
|
||||
|
||||
void LocalMap::removeCell(MWWorld::CellStore *cell)
|
||||
|
@ -293,7 +287,11 @@ void LocalMap::removeCell(MWWorld::CellStore *cell)
|
|||
saveFogOfWar(cell);
|
||||
|
||||
if (cell->isExterior())
|
||||
mSegments.erase(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
|
||||
{
|
||||
std::pair<int, int> coords = std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY());
|
||||
mSegments.erase(coords);
|
||||
mCurrentGrid.erase(coords);
|
||||
}
|
||||
else
|
||||
mSegments.clear();
|
||||
}
|
||||
|
|
|
@ -45,13 +45,12 @@ namespace MWRender
|
|||
void clear();
|
||||
|
||||
/**
|
||||
* Request a map render for the given cells. Render textures will be immediately created and can be retrieved with the getMapTexture function.
|
||||
* Request a map render for the given cell. Render textures will be immediately created and can be retrieved with the getMapTexture function.
|
||||
*/
|
||||
void requestMap (std::set<const MWWorld::CellStore*> cells);
|
||||
void requestMap (const MWWorld::CellStore* cell);
|
||||
|
||||
void addCell(MWWorld::CellStore* cell);
|
||||
|
||||
/**
|
||||
* Remove map and fog textures for the given cell.
|
||||
*/
|
||||
void removeCell (MWWorld::CellStore* cell);
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> getMapTexture (int x, int y);
|
||||
|
@ -110,6 +109,9 @@ namespace MWRender
|
|||
|
||||
CameraVector mCamerasPendingRemoval;
|
||||
|
||||
typedef std::set<std::pair<int, int> > Grid;
|
||||
Grid mCurrentGrid;
|
||||
|
||||
struct MapSegment
|
||||
{
|
||||
MapSegment();
|
||||
|
@ -124,7 +126,7 @@ namespace MWRender
|
|||
osg::ref_ptr<osg::Texture2D> mFogOfWarTexture;
|
||||
osg::ref_ptr<osg::Image> mFogOfWarImage;
|
||||
|
||||
std::set<std::pair<int, int> > mGrid; // the grid that was active at the time of rendering this segment
|
||||
Grid mGrid; // the grid that was active at the time of rendering this segment
|
||||
|
||||
bool mHasFogState;
|
||||
};
|
||||
|
|
|
@ -429,6 +429,7 @@ namespace MWWorld
|
|||
insertCell (*cell, true, loadingListener);
|
||||
|
||||
mRendering.addCell(cell);
|
||||
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
||||
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
|
||||
float waterLevel = cell->getWaterLevel();
|
||||
mRendering.setWaterEnabled(waterEnabled);
|
||||
|
|
|
@ -112,5 +112,5 @@ local map cell distance
|
|||
:Default: 1
|
||||
|
||||
Similar to "exterior cell load distance" in the Cells section, controls how many cells are rendered on the local map.
|
||||
Values higher than the default may result in longer loading times. Please note that only loaded cells can be rendered,
|
||||
Please note that only loaded cells can be rendered,
|
||||
so this setting must be lower or equal to "exterior cell load distance" to work properly.
|
||||
|
|
Loading…
Reference in a new issue