Do not re-render maps for all active cells during cell transitions

pull/541/head
bzzt 6 years ago committed by Andrei Kortunov
parent 368d1f9d25
commit ed4ce4609b

@ -350,6 +350,7 @@ namespace MWBase
virtual std::string correctTexturePath(const std::string& path) = 0; virtual std::string correctTexturePath(const std::string& path) = 0;
virtual bool textureExists(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 removeCell(MWWorld::CellStore* cell) = 0;
virtual void writeFog(MWWorld::CellStore* cell) = 0; virtual void writeFog(MWWorld::CellStore* cell) = 0;

@ -237,9 +237,6 @@ namespace MWGui
{ {
for (int my=0; my<mNumCells; ++my) for (int my=0; my<mNumCells; ++my)
{ {
int x = mCurX + (mx - mCellDistance);
int y = mCurY + (-1*(my - mCellDistance));
MapEntry& entry = mMaps[my + mNumCells*mx]; MapEntry& entry = mMaps[my + mNumCells*mx];
MyGUI::ImageBox* fog = entry.mFogWidget; MyGUI::ImageBox* fog = entry.mFogWidget;
@ -249,19 +246,6 @@ namespace MWGui
entry.mFogTexture.reset(); entry.mFogTexture.reset();
continue; 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; mInterior = interior;
mChanged = false; mChanged = false;
applyFogOfWar();
// Update the map textures
for (int mx=0; mx<mNumCells; ++mx) for (int mx=0; mx<mNumCells; ++mx)
{ {
for (int my=0; my<mNumCells; ++my) for (int my=0; my<mNumCells; ++my)
{ {
int mapX = x + (mx - mCellDistance);
int mapY = y + (-1*(my - mCellDistance));
MapEntry& entry = mMaps[my + mNumCells*mx]; 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); entry.mCellX = x + (mx - mCellDistance);
if (texture) entry.mCellY = y - (my - mCellDistance);
{
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();
}
} }
} }
@ -404,22 +375,7 @@ namespace MWGui
void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell) void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell)
{ {
std::set<const MWWorld::CellStore*> cells; mLocalMapRender->requestMap(cell);
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);
} }
void LocalMapBase::redraw() void LocalMapBase::redraw()
@ -522,6 +478,68 @@ namespace MWGui
mMarkerUpdateTimer = 0; mMarkerUpdateTimer = 0;
updateMagicMarkers(); 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() void LocalMapBase::updateDoorMarkers()

@ -129,12 +129,14 @@ namespace MWGui
struct MapEntry struct MapEntry
{ {
MapEntry(MyGUI::ImageBox* mapWidget, MyGUI::ImageBox* fogWidget) MapEntry(MyGUI::ImageBox* mapWidget, MyGUI::ImageBox* fogWidget)
: mMapWidget(mapWidget), mFogWidget(fogWidget) {} : mMapWidget(mapWidget), mFogWidget(fogWidget), mCellX(0), mCellY(0) {}
MyGUI::ImageBox* mMapWidget; MyGUI::ImageBox* mMapWidget;
MyGUI::ImageBox* mFogWidget; MyGUI::ImageBox* mFogWidget;
std::shared_ptr<MyGUI::ITexture> mMapTexture; std::shared_ptr<MyGUI::ITexture> mMapTexture;
std::shared_ptr<MyGUI::ITexture> mFogTexture; std::shared_ptr<MyGUI::ITexture> mFogTexture;
int mCellX;
int mCellY;
}; };
std::vector<MapEntry> mMaps; std::vector<MapEntry> mMaps;
@ -155,6 +157,8 @@ namespace MWGui
virtual void customMarkerCreated(MyGUI::Widget* marker) {} virtual void customMarkerCreated(MyGUI::Widget* marker) {}
virtual void doorMarkerCreated(MyGUI::Widget* marker) {} virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
void updateRequiredMaps();
void updateMagicMarkers(); void updateMagicMarkers();
void addDetectionMarkers(int type); void addDetectionMarkers(int type);

@ -976,6 +976,12 @@ namespace MWGui
void WindowManager::onFrame (float frameDuration) void WindowManager::onFrame (float frameDuration)
{ {
bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!=
MWBase::StateManager::State_NoGame;
if (gameRunning)
updateMap();
if (!mGuiModes.empty()) if (!mGuiModes.empty())
{ {
GuiModeState& state = mGuiModeStates[mGuiModes.back()]; GuiModeState& state = mGuiModeStates[mGuiModes.back()];
@ -1019,14 +1025,11 @@ namespace MWGui
if (mLocalMapRender) if (mLocalMapRender)
mLocalMapRender->cleanupCameras(); mLocalMapRender->cleanupCameras();
if (MWBase::Environment::get().getStateManager()->getState()== if (!gameRunning)
MWBase::StateManager::State_NoGame)
return; return;
mDragAndDrop->onFrame(); mDragAndDrop->onFrame();
updateMap();
mHud->onFrame(frameDuration); mHud->onFrame(frameDuration);
mDebugWindow->onFrame(frameDuration); mDebugWindow->onFrame(frameDuration);
@ -2163,6 +2166,11 @@ namespace MWGui
tex->unlock(); tex->unlock();
} }
void WindowManager::addCell(MWWorld::CellStore* cell)
{
mLocalMapRender->addCell(cell);
}
void WindowManager::removeCell(MWWorld::CellStore *cell) void WindowManager::removeCell(MWWorld::CellStore *cell)
{ {
mLocalMapRender->removeCell(cell); mLocalMapRender->removeCell(cell);

@ -378,6 +378,7 @@ namespace MWGui
virtual std::string correctTexturePath(const std::string& path); virtual std::string correctTexturePath(const std::string& path);
virtual bool textureExists(const std::string& path); virtual bool textureExists(const std::string& path);
void addCell(MWWorld::CellStore* cell);
void removeCell(MWWorld::CellStore* cell); void removeCell(MWWorld::CellStore* cell);
void writeFog(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; 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; if (cell->isExterior())
for (const MWWorld::CellStore* cell : cells)
{ {
if (cell->isExterior()) int cellX = cell->getCell()->getGridX();
grid.insert(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())); int cellY = cell->getCell()->getGridY();
}
for (const MWWorld::CellStore* cell : cells) MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
{ if (!needUpdate(segment.mGrid, mCurrentGrid, cellX, cellY))
if (cell->isExterior()) return;
else
{ {
int cellX = cell->getCell()->getGridX(); segment.mGrid = mCurrentGrid;
int cellY = cell->getCell()->getGridY(); requestExteriorMap(cell);
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
if (!needUpdate(segment.mGrid, grid, cellX, cellY))
{
continue;
}
else
{
segment.mGrid = grid;
requestExteriorMap(cell);
}
} }
else
requestInteriorMap(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) void LocalMap::removeCell(MWWorld::CellStore *cell)
@ -293,7 +287,11 @@ void LocalMap::removeCell(MWWorld::CellStore *cell)
saveFogOfWar(cell); saveFogOfWar(cell);
if (cell->isExterior()) 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 else
mSegments.clear(); mSegments.clear();
} }

@ -45,13 +45,12 @@ namespace MWRender
void clear(); 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); void removeCell (MWWorld::CellStore* cell);
osg::ref_ptr<osg::Texture2D> getMapTexture (int x, int y); osg::ref_ptr<osg::Texture2D> getMapTexture (int x, int y);
@ -110,6 +109,9 @@ namespace MWRender
CameraVector mCamerasPendingRemoval; CameraVector mCamerasPendingRemoval;
typedef std::set<std::pair<int, int> > Grid;
Grid mCurrentGrid;
struct MapSegment struct MapSegment
{ {
MapSegment(); MapSegment();
@ -124,7 +126,7 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> mFogOfWarTexture; osg::ref_ptr<osg::Texture2D> mFogOfWarTexture;
osg::ref_ptr<osg::Image> mFogOfWarImage; 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; bool mHasFogState;
}; };

@ -431,6 +431,7 @@ namespace MWWorld
insertCell (*cell, true, loadingListener); insertCell (*cell, true, loadingListener);
mRendering.addCell(cell); mRendering.addCell(cell);
MWBase::Environment::get().getWindowManager()->addCell(cell);
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior(); bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
float waterLevel = cell->getWaterLevel(); float waterLevel = cell->getWaterLevel();
mRendering.setWaterEnabled(waterEnabled); mRendering.setWaterEnabled(waterEnabled);

@ -112,5 +112,5 @@ local map cell distance
:Default: 1 :Default: 1
Similar to "exterior cell load distance" in the Cells section, controls how many cells are rendered on the local map. 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. so this setting must be lower or equal to "exterior cell load distance" to work properly.

Loading…
Cancel
Save