From 99cd4b6742b4bcc23b697b6eaf23ab4d1bfc07de Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Mon, 9 Nov 2020 14:06:50 +0100 Subject: [PATCH 1/9] [Refactoring] Several refactorings: [Refactoring] Add marker size method instead of using magic constant [Refactoring] Simplify worldPosToImageSpace and cellTopLeftCornerToImageSpace usage [Refactoring] Add a missing 'f' to specify the float type [Refactoring] Make cellTopLeftCornerToImageSpace more homogenous with worldPosToImageSpace [Refactoring] Extract createmakrercoords method [Refactoring] Use worldPosToImageSpace instead of cellTopLeftCornerToImageSpace Remove cellTopLeftCornerToImageSpace as it is not used anymore Remove getCellSize as it is not used anymore [Refactoring] Extract new method createMarker [Refactoring] Extract new method getMarkerCoordinates [Refactoring] Extract new method getPosition [Refactoring] Extract new method centerView [Refactoring] Extract new method createDoorMarker [Refactoring] Simplify for loop [Refactoring] Make the test before the loop --- apps/openmw/mwgui/mapwindow.cpp | 240 +++++++++++++++-------------- apps/openmw/mwgui/mapwindow.hpp | 11 +- apps/openmw/mwrender/globalmap.cpp | 12 +- apps/openmw/mwrender/globalmap.hpp | 4 - 4 files changed, 134 insertions(+), 133 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 6e8804a43f..f90f5c133a 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -167,7 +167,7 @@ namespace MWGui , mFogOfWarToggled(true) , mFogOfWarEnabled(fogOfWarEnabled) , mMapWidgetSize(0) - , mNumCells(0) + , mNumCells(1) , mCellDistance(0) , mCustomMarkers(markers) , mMarkerUpdateTimer(0.0f) @@ -234,65 +234,82 @@ namespace MWGui void LocalMapBase::applyFogOfWar() { - for (int mx=0; mxsetImageTexture(""); - entry.mFogTexture.reset(); - continue; - } + entry.mFogWidget->setImageTexture(""); + entry.mFogTexture.reset(); } } redraw(); } - MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos) + MyGUI::IntPoint LocalMapBase::getPosition(int cellX, int cellY, float nX, float nY) const { - MyGUI::IntPoint widgetPos; + // normalized cell coordinates + auto mapWidgetSize = getWidgetSize(); + return MyGUI::IntPoint( + static_cast(nX * mapWidgetSize + (mCellDistance + (cellX - mCurX)) * mapWidgetSize), + static_cast(nY * mapWidgetSize + (mCellDistance - (cellY - mCurY)) * mapWidgetSize) + ); + } + + MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos) const + { + int cellX, cellY; // normalized cell coordinates float nX,nY; if (!mInterior) { - int cellX, cellY; MWBase::Environment::get().getWorld()->positionToIndex(worldX, worldY, cellX, cellY); nX = (worldX - cellSize * cellX) / cellSize; // Image space is -Y up, cells are Y up nY = 1 - (worldY - cellSize * cellY) / cellSize; - - float cellDx = static_cast(cellX - mCurX); - float cellDy = static_cast(cellY - mCurY); - - markerPos.cellX = cellX; - markerPos.cellY = cellY; - - widgetPos = MyGUI::IntPoint(static_cast(nX * mMapWidgetSize + (mCellDistance + cellDx) * mMapWidgetSize), - static_cast(nY * mMapWidgetSize + (mCellDistance - cellDy) * mMapWidgetSize)); } else - { - int cellX, cellY; - osg::Vec2f worldPos (worldX, worldY); - mLocalMapRender->worldToInteriorMapPosition(worldPos, nX, nY, cellX, cellY); - - markerPos.cellX = cellX; - markerPos.cellY = cellY; - - // Image space is -Y up, cells are Y up - widgetPos = MyGUI::IntPoint(static_cast(nX * mMapWidgetSize + (mCellDistance + (cellX - mCurX)) * mMapWidgetSize), - static_cast(nY * mMapWidgetSize + (mCellDistance - (cellY - mCurY)) * mMapWidgetSize)); - } + mLocalMapRender->worldToInteriorMapPosition({ worldX, worldY }, nX, nY, cellX, cellY); + markerPos.cellX = cellX; + markerPos.cellY = cellY; markerPos.nX = nX; markerPos.nY = nY; - return widgetPos; + return getPosition(markerPos.cellX, markerPos.cellY, markerPos.nX, markerPos.nY); + } + + MyGUI::IntCoord LocalMapBase::getMarkerCoordinates(float worldX, float worldY, MarkerUserData& markerPos, size_t markerSize) const + { + int halfMarkerSize = markerSize / 2; + auto position = getMarkerPosition(worldX, worldY, markerPos); + return MyGUI::IntCoord(position.left - halfMarkerSize, position.top - halfMarkerSize, markerSize, markerSize); + } + + MyGUI::Widget* LocalMapBase::createDoorMarker(const std::string& name, const MyGUI::VectorString& notes, float x, float y) const + { + MarkerUserData data(mLocalMapRender); + data.notes = notes; + data.caption = name; + MarkerWidget* markerWidget = mLocalMap->createWidget("MarkerButton", + getMarkerCoordinates(x, y, data, 8), MyGUI::Align::Default); + markerWidget->setNormalColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}"))); + markerWidget->setHoverColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal_over}"))); + markerWidget->setDepth(Local_MarkerLayer); + markerWidget->setNeedMouseFocus(true); + // Used by tooltips to not show the tooltip if marker is hidden by fog of war + markerWidget->setUserString("ToolTipType", "MapMarker"); + + markerWidget->setUserData(data); + return markerWidget; + } + + void LocalMapBase::centerView() + { + MyGUI::IntPoint pos = mCompass->getPosition() + MyGUI::IntPoint{ 16, 16 }; + MyGUI::IntSize viewsize = mLocalMap->getSize(); + MyGUI::IntPoint viewOffset((viewsize.width / 2) - pos.left, (viewsize.height / 2) - pos.top); + mLocalMap->setViewOffset(viewOffset); } void LocalMapBase::updateCustomMarkers() @@ -317,13 +334,8 @@ namespace MWGui const ESM::CustomMarker& marker = it->second; MarkerUserData markerPos (mLocalMapRender); - MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos); - - MyGUI::IntCoord widgetCoord(widgetPos.left - 8, - widgetPos.top - 8, - 16, 16); MarkerWidget* markerWidget = mLocalMap->createWidget("CustomMarkerButton", - widgetCoord, MyGUI::Align::Default); + getMarkerCoordinates(marker.mWorldX, marker.mWorldY, markerPos, 16), MyGUI::Align::Default); markerWidget->setDepth(Local_MarkerAboveFogLayer); markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); @@ -385,21 +397,21 @@ namespace MWGui mLocalMap->getParent()->_updateChilds(); } + float LocalMapBase::getWidgetSize() const + { + return mMapWidgetSize; + } + void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny) { - MyGUI::IntPoint pos(static_cast(mMapWidgetSize * mCellDistance + nx*mMapWidgetSize - 16), static_cast(mMapWidgetSize * mCellDistance + ny*mMapWidgetSize - 16)); - pos.left += (cellX - mCurX) * mMapWidgetSize; - pos.top -= (cellY - mCurY) * mMapWidgetSize; + MyGUI::IntPoint pos = getPosition(cellX, cellY, nx, ny) - MyGUI::IntPoint{ 16, 16 }; if (pos != mCompass->getPosition()) { notifyPlayerUpdate (); mCompass->setPosition(pos); - MyGUI::IntPoint middle (pos.left+16, pos.top+16); - MyGUI::IntCoord viewsize = mLocalMap->getCoord(); - MyGUI::IntPoint viewOffset((viewsize.width / 2) - middle.left, (viewsize.height / 2) - middle.top); - mLocalMap->setViewOffset(viewOffset); + centerView(); } } @@ -449,13 +461,9 @@ namespace MWGui { const ESM::Position& worldPos = ptr.getRefData().getPosition(); MarkerUserData markerPos (mLocalMapRender); - MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos); - MyGUI::IntCoord widgetCoord(widgetPos.left - 4, - widgetPos.top - 4, - 8, 8); ++counter; MyGUI::ImageBox* markerWidget = mLocalMap->createWidget("ImageBox", - widgetCoord, MyGUI::Align::Default); + getMarkerCoordinates(worldPos.pos[0], worldPos.pos[1], markerPos, 8), MyGUI::Align::Default); markerWidget->setDepth(Local_MarkerAboveFogLayer); markerWidget->setImageTexture(markerTexture); markerWidget->setImageCoord(MyGUI::IntCoord(0,0,8,8)); @@ -561,18 +569,17 @@ namespace MWGui } else { - for (int dX=-mCellDistance; dX<=mCellDistance; ++dX) + for (int x = mCurX - mCellDistance; x <= mCurX + mCellDistance; ++x) { - for (int dY=-mCellDistance; dY<=mCellDistance; ++dY) + for (int y = mCurY - mCellDistance; y <= mCurY + mCellDistance; ++y) { - MWWorld::CellStore* cell = world->getExterior (mCurX+dX, mCurY+dY); + MWWorld::CellStore* cell = world->getExterior (x, y); world->getDoorMarkers(cell, doors); } } } // Create a widget for each marker - int counter = 0; for (MWBase::World::DoorMarker& marker : doors) { std::vector destNotes; @@ -580,24 +587,7 @@ namespace MWGui for (CustomMarkerCollection::ContainerType::const_iterator iter = markers.first; iter != markers.second; ++iter) destNotes.push_back(iter->second.mNote); - MarkerUserData data (mLocalMapRender); - data.notes = destNotes; - data.caption = marker.name; - MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, data); - MyGUI::IntCoord widgetCoord(widgetPos.left - 4, - widgetPos.top - 4, - 8, 8); - ++counter; - MarkerWidget* markerWidget = mLocalMap->createWidget("MarkerButton", - widgetCoord, MyGUI::Align::Default); - markerWidget->setNormalColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}"))); - markerWidget->setHoverColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal_over}"))); - markerWidget->setDepth(Local_MarkerLayer); - markerWidget->setNeedMouseFocus(true); - // Used by tooltips to not show the tooltip if marker is hidden by fog of war - markerWidget->setUserString("ToolTipType", "MapMarker"); - - markerWidget->setUserData(data); + MyGUI::Widget* markerWidget = createDoorMarker(marker.name, destNotes, marker.x, marker.y); doorMarkerCreated(markerWidget); mDoorMarkerWidgets.push_back(markerWidget); @@ -623,12 +613,8 @@ namespace MWGui && (!mInterior || Misc::StringUtils::ciEqual(markedCell->getCell()->mName, mPrefix))) { MarkerUserData markerPos (mLocalMapRender); - MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos); - MyGUI::IntCoord widgetCoord(widgetPos.left - 4, - widgetPos.top - 4, - 8, 8); MyGUI::ImageBox* markerWidget = mLocalMap->createWidget("ImageBox", - widgetCoord, MyGUI::Align::Default); + getMarkerCoordinates(markedPosition.pos[0], markedPosition.pos[1], markerPos, 8), MyGUI::Align::Default); markerWidget->setDepth(Local_MarkerAboveFogLayer); markerWidget->setImageTexture("textures\\menu_map_smark.dds"); markerWidget->setNeedMouseFocus(false); @@ -745,10 +731,11 @@ namespace MWGui MyGUI::IntPoint clickedPos = MyGUI::InputManager::getInstance().getMousePosition(); MyGUI::IntPoint widgetPos = clickedPos - mEventBoxLocal->getAbsolutePosition(); - int x = int(widgetPos.left/float(mMapWidgetSize))-mCellDistance; - int y = (int(widgetPos.top/float(mMapWidgetSize))-mCellDistance)*-1; - float nX = widgetPos.left/float(mMapWidgetSize) - int(widgetPos.left/float(mMapWidgetSize)); - float nY = widgetPos.top/float(mMapWidgetSize) - int(widgetPos.top/float(mMapWidgetSize)); + auto mapWidgetSize = getWidgetSize(); + int x = int(widgetPos.left/float(mapWidgetSize))-mCellDistance; + int y = (int(widgetPos.top/float(mapWidgetSize))-mCellDistance)*-1; + float nX = widgetPos.left/float(mapWidgetSize) - int(widgetPos.left/float(mapWidgetSize)); + float nY = widgetPos.top/float(mapWidgetSize) - int(widgetPos.top/float(mapWidgetSize)); x += mCurX; y += mCurY; @@ -818,6 +805,39 @@ namespace MWGui setTitle("#{sCell=" + cellName + "}"); } + MyGUI::IntCoord MapWindow::createMarkerCoords(float x, float y) const + { + float worldX, worldY; + mGlobalMapRender->worldPosToImageSpace((x + 0.5f) * Constants::CellSizeInUnits, (y + 0.5f)* Constants::CellSizeInUnits, worldX, worldY); + + const float markerSize = getMarkerSize(); + const float halfMarkerSize = markerSize / 2.0f; + return MyGUI::IntCoord( + static_cast(worldX - halfMarkerSize), + static_cast(worldY - halfMarkerSize), + markerSize, markerSize); + } + + MyGUI::Widget* MapWindow::createMarker(const std::string& name, float x, float y) + { + MyGUI::Widget* markerWidget = mGlobalMap->createWidget("MarkerButton", + createMarkerCoords(x, y), MyGUI::Align::Default); + + markerWidget->setUserString("Caption_TextOneLine", "#{sCell=" + name + "}"); + + setGlobalMapMarkerTooltip(markerWidget, x, y); + + markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); + + markerWidget->setNeedMouseFocus(true); + markerWidget->setColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}"))); + markerWidget->setDepth(Global_MarkerLayer); + markerWidget->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); + markerWidget->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); + + return markerWidget; + } + void MapWindow::addVisitedLocation(const std::string& name, int x, int y) { CellId cell; @@ -825,31 +845,7 @@ namespace MWGui cell.second = y; if (mMarkers.insert(cell).second) { - float worldX, worldY; - mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY); - - int markerSize = 12; - int offset = mGlobalMapRender->getCellSize()/2 - markerSize/2; - MyGUI::IntCoord widgetCoord( - static_cast(worldX * mGlobalMapRender->getWidth()+offset), - static_cast(worldY * mGlobalMapRender->getHeight() + offset), - markerSize, markerSize); - - MyGUI::Widget* markerWidget = mGlobalMap->createWidget("MarkerButton", - widgetCoord, MyGUI::Align::Default); - - markerWidget->setUserString("Caption_TextOneLine", "#{sCell=" + name + "}"); - - setGlobalMapMarkerTooltip(markerWidget, x, y); - - markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); - - markerWidget->setNeedMouseFocus(true); - markerWidget->setColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}"))); - markerWidget->setDepth(Global_MarkerLayer); - markerWidget->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); - markerWidget->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); - mGlobalMapMarkers[std::make_pair(x,y)] = markerWidget; + mGlobalMapMarkers[std::make_pair(x, y)] = createMarker(name, x, y); } } @@ -891,6 +887,11 @@ namespace MWGui } } + float MapWindow::getMarkerSize() const + { + return 12.0f; + } + void MapWindow::updateCustomMarkers() { LocalMapBase::updateCustomMarkers(); @@ -978,19 +979,22 @@ namespace MWGui setGlobalMapPlayerDir(mLastDirectionX, mLastDirectionY); } + void MapWindow::centerView() + { + // set the view offset so that player is in the center + MyGUI::IntSize viewsize = mGlobalMap->getSize(); + MyGUI::IntPoint pos = mPlayerArrowGlobal->getPosition() + MyGUI::IntPoint{ 16,16 }; + MyGUI::IntPoint viewoffs(static_cast(viewsize.width * 0.5f - pos.left), static_cast(viewsize.height * 0.5f - pos.top)); + mGlobalMap->setViewOffset(viewoffs); + } + void MapWindow::setGlobalMapPlayerPosition(float worldX, float worldY) { float x, y; mGlobalMapRender->worldPosToImageSpace (worldX, worldY, x, y); - x *= mGlobalMapRender->getWidth(); - y *= mGlobalMapRender->getHeight(); - mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(static_cast(x - 16), static_cast(y - 16))); - // set the view offset so that player is in the center - MyGUI::IntSize viewsize = mGlobalMap->getSize(); - MyGUI::IntPoint viewoffs(static_cast(viewsize.width * 0.5f - x), static_cast(viewsize.height *0.5 - y)); - mGlobalMap->setViewOffset(viewoffs); + centerView(); } void MapWindow::setGlobalMapPlayerDir(const float x, const float y) diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 7e8092f289..f4559b9abf 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -149,9 +149,13 @@ namespace MWGui void applyFogOfWar(); - MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerUserData& markerPos); + MyGUI::IntPoint getPosition(int cellX, int cellY, float nx, float ny) const; + MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerUserData& markerPos) const; + MyGUI::IntCoord getMarkerCoordinates(float worldX, float worldY, MarkerUserData& markerPos, size_t markerSize) const; + MyGUI::Widget* createDoorMarker(const std::string& name, const MyGUI::VectorString& notes, float x, float y) const; virtual void notifyPlayerUpdate() {} + void centerView(); virtual void notifyMapChanged() {} virtual void customMarkerCreated(MyGUI::Widget* marker) {} @@ -163,6 +167,7 @@ namespace MWGui void addDetectionMarkers(int type); void redraw(); + float getWidgetSize() const; float mMarkerUpdateTimer; @@ -252,6 +257,9 @@ namespace MWGui void onChangeScrollWindowCoord(MyGUI::Widget* sender); void globalMapUpdatePlayer(); void setGlobalMapMarkerTooltip(MyGUI::Widget* widget, int x, int y); + float getMarkerSize() const; + MyGUI::IntCoord createMarkerCoords(float x, float y) const; + MyGUI::Widget* createMarker(const std::string& name, float x, float y); MyGUI::ScrollView* mGlobalMap; std::unique_ptr mGlobalMapTexture; @@ -288,6 +296,7 @@ namespace MWGui void notifyPlayerUpdate() override; + void centerView(); }; } #endif diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 8784eb501a..dcaf9c1612 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -270,17 +270,9 @@ namespace MWRender void GlobalMap::worldPosToImageSpace(float x, float z, float& imageX, float& imageY) { - imageX = float(x / float(Constants::CellSizeInUnits) - mMinX) / (mMaxX - mMinX + 1); + imageX = (float(x / float(Constants::CellSizeInUnits) - mMinX) / (mMaxX - mMinX + 1)) * getWidth(); - imageY = 1.f-float(z / float(Constants::CellSizeInUnits) - mMinY) / (mMaxY - mMinY + 1); - } - - void GlobalMap::cellTopLeftCornerToImageSpace(int x, int y, float& imageX, float& imageY) - { - imageX = float(x - mMinX) / (mMaxX - mMinX + 1); - - // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is - imageY = 1.f-float(y - mMinY + 1) / (mMaxY - mMinY + 1); + imageY = (1.f-float(z / float(Constants::CellSizeInUnits) - mMinY) / (mMaxY - mMinY + 1)) * getHeight(); } void GlobalMap::requestOverlayTextureUpdate(int x, int y, int width, int height, osg::ref_ptr texture, bool clear, bool cpuCopy, diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index b359c852be..fd8a8d1016 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -41,12 +41,8 @@ namespace MWRender int getWidth() const { return mWidth; } int getHeight() const { return mHeight; } - int getCellSize() const { return mCellSize; } - void worldPosToImageSpace(float x, float z, float& imageX, float& imageY); - void cellTopLeftCornerToImageSpace(int x, int y, float& imageX, float& imageY); - void exploreCell (int cellX, int cellY, osg::ref_ptr localMapTexture); /// Clears the overlay From 3373afcc83ab3599d99c026f3ec74e3ce46c0de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Sat, 24 Jul 2021 17:42:04 +0200 Subject: [PATCH 2/9] [Settings] Set values --- docs/source/reference/modding/settings/map.rst | 11 +++++++++++ files/settings-default.cfg | 3 +++ 2 files changed, 14 insertions(+) diff --git a/docs/source/reference/modding/settings/map.rst b/docs/source/reference/modding/settings/map.rst index ac989f3dea..b0e30789ac 100644 --- a/docs/source/reference/modding/settings/map.rst +++ b/docs/source/reference/modding/settings/map.rst @@ -103,3 +103,14 @@ and typically require more panning to see all available portions of the map. This larger size also enables an overall greater level of detail if the local map resolution setting is also increased. This setting can not be configured except by editing the settings configuration file. + +allow zooming +------------- + +:Type: boolean +:Range: True/False +:Default: False + +If this setting is true the user can zoom in/out on local and global map with the mouse wheel. + +This setting can be controlled in Advanced tab of the launcher. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index e7439fb5ae..c3c22c061c 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -199,6 +199,9 @@ local map widget size = 512 # If true, map in world mode, otherwise in local mode global = false +# If true, allow zoom on local and global maps +allow zooming = false + [GUI] # Scales GUI window and widget size. (<1.0 is smaller, >1.0 is larger). From 9fadbd5b7aebdb299d2294091d20f2c7574f0793 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Sat, 21 Nov 2020 16:37:42 +0100 Subject: [PATCH 3/9] [Global map] Allow zoom on global map --- apps/openmw/mwgui/mapwindow.cpp | 78 +++++++++++++++++++++++++++++---- apps/openmw/mwgui/mapwindow.hpp | 6 +++ 2 files changed, 76 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index f90f5c133a..a9efe0af42 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -34,6 +34,7 @@ namespace { const int cellSize = Constants::CellSizeInUnits; + constexpr float speed = 1.08; //the zoom speed, it should be greater than 1 enum LocalMapWidgetDepth { @@ -676,6 +677,7 @@ namespace MWGui getWidget(mEventBoxGlobal, "EventBoxGlobal"); mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); + mEventBoxGlobal->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed); mEventBoxGlobal->setDepth(Global_ExploreOverlayLayer); getWidget(mEventBoxLocal, "EventBoxLocal"); @@ -768,6 +770,57 @@ namespace MWGui mEditNoteDialog.setText(""); } + void MapWindow::onMapZoomed(MyGUI::Widget* sender, int rel) + { + const bool zoomOut = rel < 0; + const bool zoomIn = !zoomOut; + const double speedDiff = zoomOut ? 1.0 / speed : speed; + + if (mGlobal) + { + const float currentGlobalZoom = mGlobalMapZoom; + const float currentMinGlobalMapZoom = std::min( + float(mGlobalMap->getWidth()) / float(mGlobalMapRender->getWidth()), + float(mGlobalMap->getHeight()) / float(mGlobalMapRender->getHeight()) + ); + + mGlobalMapZoom *= speedDiff; + + if (zoomIn && mGlobalMapZoom > 4.f) + { + mGlobalMapZoom = currentGlobalZoom; + return; //the zoom in is too big + } + + if (zoomOut && mGlobalMapZoom < currentMinGlobalMapZoom) + { + mGlobalMapZoom = currentGlobalZoom; + return; //the zoom out is too big, we have reach the borders of the widget + } + zoomOnCursor(speedDiff); + } + } + + void MapWindow::zoomOnCursor(float speedDiff) + { + auto cursor = MyGUI::InputManager::getInstance().getMousePosition() - mGlobalMap->getAbsolutePosition(); + auto centerView = mGlobalMap->getViewOffset() - cursor; + updateGlobalMap(); + mGlobalMap->setViewOffset(MyGUI::IntPoint( + std::round(centerView.left * speedDiff) + cursor.left, + std::round(centerView.top * speedDiff) + cursor.top + )); + } + + void MapWindow::updateGlobalMap() + { + resizeGlobalMap(); + notifyPlayerUpdate(); + + for (auto& marker : mGlobalMapMarkers) + marker.second->setCoord(createMarkerCoords(marker.first.first, marker.first.second)); + } + void MapWindow::onChangeScrollWindowCoord(MyGUI::Widget* sender) { MyGUI::IntCoord currentCoordinates = sender->getCoord(); @@ -791,8 +844,7 @@ namespace MWGui void MapWindow::renderGlobalMap() { mGlobalMapRender->render(); - mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); - mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); + resizeGlobalMap(); } MapWindow::~MapWindow() @@ -808,7 +860,7 @@ namespace MWGui MyGUI::IntCoord MapWindow::createMarkerCoords(float x, float y) const { float worldX, worldY; - mGlobalMapRender->worldPosToImageSpace((x + 0.5f) * Constants::CellSizeInUnits, (y + 0.5f)* Constants::CellSizeInUnits, worldX, worldY); + worldPosToGlobalMapImageSpace((x + 0.5f) * Constants::CellSizeInUnits, (y + 0.5f)* Constants::CellSizeInUnits, worldX, worldY); const float markerSize = getMarkerSize(); const float halfMarkerSize = markerSize / 2.0f; @@ -833,6 +885,7 @@ namespace MWGui markerWidget->setColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}"))); markerWidget->setDepth(Global_MarkerLayer); markerWidget->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); + markerWidget->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed); markerWidget->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); return markerWidget; @@ -889,7 +942,19 @@ namespace MWGui float MapWindow::getMarkerSize() const { - return 12.0f; + return 12.0f * mGlobalMapZoom; + } + + void MapWindow::resizeGlobalMap() + { + mGlobalMap->setCanvasSize(mGlobalMapRender->getWidth() * mGlobalMapZoom, mGlobalMapRender->getHeight() * mGlobalMapZoom); + mGlobalMapImage->setSize(mGlobalMapRender->getWidth() * mGlobalMapZoom, mGlobalMapRender->getHeight() * mGlobalMapZoom); + } + + void MapWindow::worldPosToGlobalMapImageSpace(float x, float y, float& imageX, float& imageY) const + { + mGlobalMapRender->worldPosToImageSpace(x, y, imageX, imageY); + imageX *= mGlobalMapZoom, imageY *= mGlobalMapZoom; } void MapWindow::updateCustomMarkers() @@ -935,9 +1000,6 @@ namespace MWGui mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : "#{sWorld}"); - - if (mGlobal) - globalMapUpdatePlayer (); } void MapWindow::onPinToggled() @@ -991,7 +1053,7 @@ namespace MWGui void MapWindow::setGlobalMapPlayerPosition(float worldX, float worldY) { float x, y; - mGlobalMapRender->worldPosToImageSpace (worldX, worldY, x, y); + worldPosToGlobalMapImageSpace(worldX, worldY, x, y); mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(static_cast(x - 16), static_cast(y - 16))); centerView(); diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index f4559b9abf..9723c809ff 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -249,6 +249,9 @@ namespace MWGui void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onWorldButtonClicked(MyGUI::Widget* _sender); void onMapDoubleClicked(MyGUI::Widget* sender); + void onMapZoomed(MyGUI::Widget* sender, int rel); + void zoomOnCursor(float speedDiff); + void updateGlobalMap(); void onCustomMarkerDoubleClicked(MyGUI::Widget* sender); void onNoteEditOk(); void onNoteEditDelete(); @@ -258,6 +261,8 @@ namespace MWGui void globalMapUpdatePlayer(); void setGlobalMapMarkerTooltip(MyGUI::Widget* widget, int x, int y); float getMarkerSize() const; + void resizeGlobalMap(); + void worldPosToGlobalMapImageSpace(float x, float z, float& imageX, float& imageY) const; MyGUI::IntCoord createMarkerCoords(float x, float y) const; MyGUI::Widget* createMarker(const std::string& name, float x, float y); @@ -281,6 +286,7 @@ namespace MWGui MyGUI::Button* mEventBoxGlobal; MyGUI::Button* mEventBoxLocal; + float mGlobalMapZoom = 1.0f; MWRender::GlobalMap* mGlobalMapRender; std::map, MyGUI::Widget*> mGlobalMapMarkers; From ed04ebe9ffa65bc4ffff99012f849dca68ddf54d Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Thu, 26 Nov 2020 16:32:50 +0100 Subject: [PATCH 4/9] [Local map] Allow zoom on local map --- apps/openmw/mwgui/mapwindow.cpp | 103 ++++++++++++++++++++++++++++---- apps/openmw/mwgui/mapwindow.hpp | 11 +++- 2 files changed, 100 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index a9efe0af42..d7e3888fa8 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -252,8 +252,8 @@ namespace MWGui // normalized cell coordinates auto mapWidgetSize = getWidgetSize(); return MyGUI::IntPoint( - static_cast(nX * mapWidgetSize + (mCellDistance + (cellX - mCurX)) * mapWidgetSize), - static_cast(nY * mapWidgetSize + (mCellDistance - (cellY - mCurY)) * mapWidgetSize) + std::round(nX * mapWidgetSize + (mCellDistance + (cellX - mCurX)) * mapWidgetSize), + std::round(nY * mapWidgetSize + (mCellDistance - (cellY - mCurY)) * mapWidgetSize) ); } @@ -313,6 +313,13 @@ namespace MWGui mLocalMap->setViewOffset(viewOffset); } + MyGUI::IntCoord LocalMapBase::getMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const + { + MarkerUserData& markerPos(*widget->getUserData()); + auto position = getPosition(markerPos.cellX, markerPos.cellY, markerPos.nX, markerPos.nY); + return MyGUI::IntCoord(position.left - markerSize / 2, position.top - markerSize / 2, markerSize, markerSize); + } + void LocalMapBase::updateCustomMarkers() { for (MyGUI::Widget* widget : mCustomMarkerWidgets) @@ -379,6 +386,9 @@ namespace MWGui } } + for (MyGUI::Widget* widget : mDoorMarkerWidgets) + widget->setCoord(getMarkerCoordinates(widget, 8)); + // 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. mNeedDoorMarkersUpdate = true; @@ -400,7 +410,7 @@ namespace MWGui float LocalMapBase::getWidgetSize() const { - return mMapWidgetSize; + return mLocalMapZoom * mMapWidgetSize; } void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny) @@ -412,6 +422,11 @@ namespace MWGui notifyPlayerUpdate (); mCompass->setPosition(pos); + } + osg::Vec2f curPos((cellX + nx) * cellSize, (cellY + 1 - ny) * cellSize); + if ((curPos - mCurPos).length2() > 0.001) + { + mCurPos = curPos; centerView(); } } @@ -469,6 +484,7 @@ namespace MWGui markerWidget->setImageTexture(markerTexture); markerWidget->setImageCoord(MyGUI::IntCoord(0,0,8,8)); markerWidget->setNeedMouseFocus(false); + markerWidget->setUserData(markerPos); mMagicMarkerWidgets.push_back(markerWidget); } } @@ -619,12 +635,40 @@ namespace MWGui markerWidget->setDepth(Local_MarkerAboveFogLayer); markerWidget->setImageTexture("textures\\menu_map_smark.dds"); markerWidget->setNeedMouseFocus(false); + markerWidget->setUserData(markerPos); mMagicMarkerWidgets.push_back(markerWidget); } redraw(); } + void LocalMapBase::updateLocalMap() + { + auto mapWidgetSize = getWidgetSize(); + mLocalMap->setCanvasSize(mapWidgetSize * mNumCells, mapWidgetSize * mNumCells); + + const auto size = MyGUI::IntSize(std::ceil(mapWidgetSize), std::ceil(mapWidgetSize)); + for (auto& entry : mMaps) + { + const auto position = getPosition(entry.mCellX, entry.mCellY, 0, 0); + entry.mMapWidget->setCoord({ position, size }); + entry.mFogWidget->setCoord({ position, size }); + } + + MarkerUserData markerPos(mLocalMapRender); + for (MyGUI::Widget* widget : mDoorMarkerWidgets) + widget->setCoord(getMarkerCoordinates(widget, 8)); + + for (MyGUI::Widget* widget : mCustomMarkerWidgets) + { + const auto& marker = *widget->getUserData(); + widget->setCoord(getMarkerCoordinates(marker.mWorldX, marker.mWorldY, markerPos, 16)); + } + + for (MyGUI::Widget* widget : mMagicMarkerWidgets) + widget->setCoord(getMarkerCoordinates(widget, 8)); + } + // ------------------------------------------------------------------------------------------ MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue) @@ -684,6 +728,7 @@ namespace MWGui mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); mEventBoxLocal->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onMapDoubleClicked); + mEventBoxLocal->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed); LocalMapBase::init(mLocalMap, mPlayerArrowLocal); @@ -772,9 +817,17 @@ namespace MWGui void MapWindow::onMapZoomed(MyGUI::Widget* sender, int rel) { + const static int localWidgetSize = Settings::Manager::getInt("local map widget size", "Map"); + const bool zoomOut = rel < 0; const bool zoomIn = !zoomOut; const double speedDiff = zoomOut ? 1.0 / speed : speed; + const float localMapSizeInUnits = localWidgetSize * mNumCells; + + const float currentMinLocalMapZoom = std::max( + float(mLocalMap->getWidth()) / localMapSizeInUnits, + float(mLocalMap->getHeight()) / localMapSizeInUnits + ); if (mGlobal) { @@ -797,16 +850,36 @@ namespace MWGui mGlobalMapZoom = currentGlobalZoom; return; //the zoom out is too big, we have reach the borders of the widget } - zoomOnCursor(speedDiff); } + else + { + auto const currentLocalZoom = mLocalMapZoom; + mLocalMapZoom *= speedDiff; + + if (zoomIn && mLocalMapZoom > 4.0f) + { + mLocalMapZoom = currentLocalZoom; + return; //the zoom in is too big + } + + if (zoomOut && mLocalMapZoom < currentMinLocalMapZoom) + { + mLocalMapZoom = currentLocalZoom; + return; //the zoom out is too big + } + } + zoomOnCursor(speedDiff); } void MapWindow::zoomOnCursor(float speedDiff) { - auto cursor = MyGUI::InputManager::getInstance().getMousePosition() - mGlobalMap->getAbsolutePosition(); - auto centerView = mGlobalMap->getViewOffset() - cursor; - updateGlobalMap(); - mGlobalMap->setViewOffset(MyGUI::IntPoint( + auto map = mGlobal ? mGlobalMap : mLocalMap; + auto cursor = MyGUI::InputManager::getInstance().getMousePosition() - map->getAbsolutePosition(); + auto centerView = map->getViewOffset() - cursor; + + mGlobal? updateGlobalMap() : updateLocalMap(); + + map->setViewOffset(MyGUI::IntPoint( std::round(centerView.left * speedDiff) + cursor.left, std::round(centerView.top * speedDiff) + cursor.top )); @@ -815,7 +888,14 @@ namespace MWGui void MapWindow::updateGlobalMap() { resizeGlobalMap(); - notifyPlayerUpdate(); + + float x = mCurPos.x(), y = mCurPos.y(); + if (mInterior) + { + auto pos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition(); + x = pos.x(), y = pos.y(); + } + setGlobalMapPlayerPosition(x, y); for (auto& marker : mGlobalMapMarkers) marker.second->setCoord(createMarkerCoords(marker.first.first, marker.first.second)); @@ -1043,6 +1123,7 @@ namespace MWGui void MapWindow::centerView() { + LocalMapBase::centerView(); // set the view offset so that player is in the center MyGUI::IntSize viewsize = mGlobalMap->getSize(); MyGUI::IntPoint pos = mPlayerArrowGlobal->getPosition() + MyGUI::IntPoint{ 16,16 }; @@ -1055,8 +1136,6 @@ namespace MWGui float x, y; worldPosToGlobalMapImageSpace(worldX, worldY, x, y); mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(static_cast(x - 16), static_cast(y - 16))); - - centerView(); } void MapWindow::setGlobalMapPlayerDir(const float x, const float y) @@ -1141,12 +1220,14 @@ namespace MWGui marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); marker->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onCustomMarkerDoubleClicked); + marker->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed); } void MapWindow::doorMarkerCreated(MyGUI::Widget *marker) { marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); + marker->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed); } // ------------------------------------------------------------------- diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 9723c809ff..f8c398b75b 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -107,9 +107,13 @@ namespace MWGui }; protected: + void updateLocalMap(); + + float mLocalMapZoom = 1.f; MWRender::LocalMap* mLocalMapRender; - int mCurX, mCurY; + int mCurX, mCurY; //the position of the active cell on the global map (in cell coords) + osg::Vec2f mCurPos; //the position of the player in the world (in cell coords) bool mInterior; MyGUI::ScrollView* mLocalMap; MyGUI::ImageBox* mCompass; @@ -153,9 +157,10 @@ namespace MWGui MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerUserData& markerPos) const; MyGUI::IntCoord getMarkerCoordinates(float worldX, float worldY, MarkerUserData& markerPos, size_t markerSize) const; MyGUI::Widget* createDoorMarker(const std::string& name, const MyGUI::VectorString& notes, float x, float y) const; + MyGUI::IntCoord getMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const; virtual void notifyPlayerUpdate() {} - void centerView(); + virtual void centerView(); virtual void notifyMapChanged() {} virtual void customMarkerCreated(MyGUI::Widget* marker) {} @@ -302,7 +307,7 @@ namespace MWGui void notifyPlayerUpdate() override; - void centerView(); + void centerView() override; }; } #endif From 8c87defddf8dd3c31ac949db857b02793187fb25 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Tue, 3 Nov 2020 08:08:50 +0100 Subject: [PATCH 5/9] [Local map] Use the distance view in the local map --- apps/openmw/mwgui/mapwindow.cpp | 130 +++++++++++++----- apps/openmw/mwgui/mapwindow.hpp | 13 +- apps/openmw/mwrender/localmap.cpp | 68 ++++----- apps/openmw/mwrender/localmap.hpp | 6 +- .../source/reference/modding/settings/map.rst | 12 ++ files/settings-default.cfg | 3 + 6 files changed, 156 insertions(+), 76 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index d7e3888fa8..9cc47e8c16 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -85,6 +85,23 @@ namespace setColour(mHoverColour); } }; + + MyGUI::IntRect createRect(const MyGUI::IntPoint& center, int radius) + { + return { center.left - radius, center.top + radius, center.left + radius, center.top - radius }; + } + + int getLocalViewingDistance() + { + if (!Settings::Manager::getBool("allow zooming", "Map")) + return Constants::CellGridRadius; + if (!Settings::Manager::getBool("distant terrain", "Terrain")) + return Constants::CellGridRadius; + const float localViewingDistanceCoef = Settings::Manager::getFloat("local viewing distance coef", "Map"); + const int viewingDistance = Settings::Manager::getInt("viewing distance", "Camera"); + const int localViewingDistanceInCells = (viewingDistance * localViewingDistanceCoef) / double(Constants::CellSizeInUnits); + return std::max(Constants::CellGridRadius, localViewingDistanceInCells); + } } namespace MWGui @@ -174,7 +191,6 @@ namespace MWGui , mMarkerUpdateTimer(0.0f) , mLastDirectionX(0.0f) , mLastDirectionY(0.0f) - , mNeedDoorMarkersUpdate(false) { mCustomMarkers.eventMarkersChanged += MyGUI::newDelegate(this, &LocalMapBase::updateCustomMarkers); } @@ -184,12 +200,12 @@ namespace MWGui mCustomMarkers.eventMarkersChanged -= MyGUI::newDelegate(this, &LocalMapBase::updateCustomMarkers); } - void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass) + void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, int cellDistance) { mLocalMap = widget; mCompass = compass; mMapWidgetSize = std::max(1, Settings::Manager::getInt("local map widget size", "Map")); - mCellDistance = Constants::CellGridRadius; + mCellDistance = cellDistance; mNumCells = mCellDistance * 2 + 1; mLocalMap->setCanvasSize(mMapWidgetSize*mNumCells, mMapWidgetSize*mNumCells); @@ -320,6 +336,11 @@ namespace MWGui return MyGUI::IntCoord(position.left - markerSize / 2, position.top - markerSize / 2, markerSize, markerSize); } + std::vector& LocalMapBase::currentDoorMarkersWidgets() + { + return mInterior ? mInteriorDoorMarkerWidgets : mExteriorDoorMarkerWidgets; + } + void LocalMapBase::updateCustomMarkers() { for (MyGUI::Widget* widget : mCustomMarkerWidgets) @@ -366,6 +387,38 @@ namespace MWGui if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell + if (!interior && !(x == mCurX && y == mCurY)) + { + const MyGUI::IntRect intersection = { + std::max(x, mCurX) - mCellDistance, std::max(y, mCurY) - mCellDistance, + std::min(x, mCurX) + mCellDistance, std::min(y, mCurY) + mCellDistance + }; + + const MyGUI::IntRect activeGrid = createRect({ x, y }, Constants::CellGridRadius); + const MyGUI::IntRect currentView = createRect({ x, y }, mCellDistance); + + mExteriorDoorMarkerWidgets.clear(); + for (auto& [coord, doors] : mExteriorDoorsByCell) + { + if (!mHasALastActiveCell || !currentView.inside({ coord.first, coord.second }) || activeGrid.inside({ coord.first, coord.second })) + { + mDoorMarkersToRecycle.insert(mDoorMarkersToRecycle.end(), doors.begin(), doors.end()); + doors.clear(); + } + else + mExteriorDoorMarkerWidgets.insert(mExteriorDoorMarkerWidgets.end(), doors.begin(), doors.end()); + } + + for (auto& widget : mDoorMarkersToRecycle) + widget->setVisible(false); + + for (auto const& cell : mMaps) + { + if (mHasALastActiveCell && !intersection.inside({ cell.mCellX, cell.mCellY })) + mLocalMapRender->removeExteriorCell(cell.mCellX, cell.mCellY); + } + } + mCurX = x; mCurY = y; mInterior = interior; @@ -386,12 +439,11 @@ namespace MWGui } } - for (MyGUI::Widget* widget : mDoorMarkerWidgets) + for (MyGUI::Widget* widget : currentDoorMarkersWidgets()) widget->setCoord(getMarkerCoordinates(widget, 8)); - // 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. - mNeedDoorMarkersUpdate = true; + if (!mInterior) + mHasALastActiveCell = true; updateMagicMarkers(); updateCustomMarkers(); @@ -491,11 +543,7 @@ namespace MWGui void LocalMapBase::onFrame(float dt) { - if (mNeedDoorMarkersUpdate) - { - updateDoorMarkers(); - mNeedDoorMarkersUpdate = false; - } + updateDoorMarkers(); mMarkerUpdateTimer += dt; @@ -570,30 +618,29 @@ namespace MWGui void LocalMapBase::updateDoorMarkers() { - // clear all previous door markers - for (MyGUI::Widget* widget : mDoorMarkerWidgets) - MyGUI::Gui::getInstance().destroyWidget(widget); - mDoorMarkerWidgets.clear(); - + std::vector doors; MWBase::World* world = MWBase::Environment::get().getWorld(); - // Retrieve the door markers we want to show - std::vector doors; + mDoorMarkersToRecycle.insert(mDoorMarkersToRecycle.end(), mInteriorDoorMarkerWidgets.begin(), mInteriorDoorMarkerWidgets.end()); + mInteriorDoorMarkerWidgets.clear(); + if (mInterior) { + for (MyGUI::Widget* widget : mExteriorDoorMarkerWidgets) + widget->setVisible(false); + MWWorld::CellStore* cell = world->getInterior (mPrefix); world->getDoorMarkers(cell, doors); } else { - for (int x = mCurX - mCellDistance; x <= mCurX + mCellDistance; ++x) + for (MapEntry& entry : mMaps) { - for (int y = mCurY - mCellDistance; y <= mCurY + mCellDistance; ++y) - { - MWWorld::CellStore* cell = world->getExterior (x, y); - world->getDoorMarkers(cell, doors); - } + if (!entry.mMapTexture && !widgetCropped(entry.mMapWidget, mLocalMap)) + world->getDoorMarkers(world->getExterior(entry.mCellX, entry.mCellY), doors); } + if (doors.empty()) + return; } // Create a widget for each marker @@ -604,11 +651,33 @@ namespace MWGui for (CustomMarkerCollection::ContainerType::const_iterator iter = markers.first; iter != markers.second; ++iter) destNotes.push_back(iter->second.mNote); - MyGUI::Widget* markerWidget = createDoorMarker(marker.name, destNotes, marker.x, marker.y); - doorMarkerCreated(markerWidget); + MyGUI::Widget* markerWidget = nullptr; + MarkerUserData* data; + if (mDoorMarkersToRecycle.empty()) + { + markerWidget = createDoorMarker(marker.name, destNotes, marker.x, marker.y); + data = markerWidget->getUserData(); + doorMarkerCreated(markerWidget); + } + else + { + markerWidget = (MarkerWidget*)mDoorMarkersToRecycle.back(); + mDoorMarkersToRecycle.pop_back(); - mDoorMarkerWidgets.push_back(markerWidget); + data = markerWidget->getUserData(); + data->notes = destNotes; + data->caption = marker.name; + markerWidget->setCoord(getMarkerCoordinates(marker.x, marker.y, *data, 8)); + markerWidget->setVisible(true); + } + + currentDoorMarkersWidgets().push_back(markerWidget); + if (!mInterior) + mExteriorDoorsByCell[{data->cellX, data->cellY}].push_back(markerWidget); } + + for (auto& widget : mDoorMarkersToRecycle) + widget->setVisible(false); } void LocalMapBase::updateMagicMarkers() @@ -656,7 +725,7 @@ namespace MWGui } MarkerUserData markerPos(mLocalMapRender); - for (MyGUI::Widget* widget : mDoorMarkerWidgets) + for (MyGUI::Widget* widget : currentDoorMarkersWidgets()) widget->setCoord(getMarkerCoordinates(widget, 8)); for (MyGUI::Widget* widget : mCustomMarkerWidgets) @@ -670,7 +739,6 @@ namespace MWGui } // ------------------------------------------------------------------------------------------ - MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue) : WindowPinnableBase("openmw_map_window.layout") , LocalMapBase(customMarkers, localMapRender) @@ -730,7 +798,7 @@ namespace MWGui mEventBoxLocal->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onMapDoubleClicked); mEventBoxLocal->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed); - LocalMapBase::init(mLocalMap, mPlayerArrowLocal); + LocalMapBase::init(mLocalMap, mPlayerArrowLocal, getLocalViewingDistance()); mGlobalMap->setVisible(mGlobal); mLocalMap->setVisible(!mGlobal); diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index f8c398b75b..f1d5d495fb 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace MWRender { @@ -72,7 +73,7 @@ namespace MWGui public: LocalMapBase(CustomMarkerCollection& markers, MWRender::LocalMap* localMapRender, bool fogOfWarEnabled = true); virtual ~LocalMapBase(); - void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass); + void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, int cellDistance = Constants::CellGridRadius); void setCellPrefix(const std::string& prefix); void setActiveCell(const int x, const int y, bool interior=false); @@ -113,7 +114,9 @@ namespace MWGui MWRender::LocalMap* mLocalMapRender; int mCurX, mCurY; //the position of the active cell on the global map (in cell coords) + bool mHasALastActiveCell = false; osg::Vec2f mCurPos; //the position of the player in the world (in cell coords) + bool mInterior; MyGUI::ScrollView* mLocalMap; MyGUI::ImageBox* mCompass; @@ -145,9 +148,14 @@ namespace MWGui std::vector mMaps; // Keep track of created marker widgets, just to easily remove them later. - std::vector mDoorMarkerWidgets; + std::vector mExteriorDoorMarkerWidgets; + std::map, std::vector> mExteriorDoorsByCell; + std::vector mInteriorDoorMarkerWidgets; std::vector mMagicMarkerWidgets; std::vector mCustomMarkerWidgets; + std::vector mDoorMarkersToRecycle; + + std::vector& currentDoorMarkersWidgets(); virtual void updateCustomMarkers(); @@ -181,7 +189,6 @@ namespace MWGui private: void updateDoorMarkers(); - bool mNeedDoorMarkersUpdate; }; class EditNoteDialog : public MWGui::WindowModal diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 24c00048d9..858d577335 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -118,14 +118,15 @@ const osg::Vec2f LocalMap::rotatePoint(const osg::Vec2f& point, const osg::Vec2f void LocalMap::clear() { - mSegments.clear(); + mExteriorSegments.clear(); + mInteriorSegments.clear(); } void LocalMap::saveFogOfWar(MWWorld::CellStore* cell) { if (!mInterior) { - const MapSegment& segment = mSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())]; + const MapSegment& segment = mExteriorSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())]; if (segment.mFogOfWarImage && segment.mHasFogState) { @@ -155,7 +156,7 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell) { for (int y = 0; y < segments.second; ++y) { - const MapSegment& segment = mSegments[std::make_pair(x,y)]; + const MapSegment& segment = mInteriorSegments[std::make_pair(x,y)]; fog->mFogTextures.emplace_back(); @@ -249,26 +250,10 @@ void LocalMap::setupRenderToTexture(osg::ref_ptr camera, int x, int mRoot->addChild(camera); mActiveCameras.push_back(camera); - MapSegment& segment = mSegments[std::make_pair(x, y)]; + MapSegment& segment = mInterior? mInteriorSegments[std::make_pair(x, y)] : mExteriorSegments[std::make_pair(x, y)]; segment.mMapTexture = texture; } -bool needUpdate(std::set >& renderedGrid, std::set >& currentGrid, int cellX, int cellY) -{ - // if all the cells of the current grid are contained in the rendered grid then we can keep the old render - for (int dx=-1;dx<2;dx+=1) - { - for (int dy=-1;dy<2;dy+=1) - { - bool haveInRenderedGrid = renderedGrid.find(std::make_pair(cellX+dx,cellY+dy)) != renderedGrid.end(); - bool haveInCurrentGrid = currentGrid.find(std::make_pair(cellX+dx,cellY+dy)) != currentGrid.end(); - if (haveInCurrentGrid && !haveInRenderedGrid) - return true; - } - } - return false; -} - void LocalMap::requestMap(const MWWorld::CellStore* cell) { if (cell->isExterior()) @@ -276,13 +261,13 @@ void LocalMap::requestMap(const MWWorld::CellStore* cell) int cellX = cell->getCell()->getGridX(); int cellY = cell->getCell()->getGridY(); - MapSegment& segment = mSegments[std::make_pair(cellX, cellY)]; - if (!needUpdate(segment.mGrid, mCurrentGrid, cellX, cellY)) + MapSegment& segment = mExteriorSegments[std::make_pair(cellX, cellY)]; + if (!segment.needUpdate) return; else { - segment.mGrid = mCurrentGrid; requestExteriorMap(cell); + segment.needUpdate = false; } } else @@ -292,27 +277,27 @@ void LocalMap::requestMap(const MWWorld::CellStore* cell) void LocalMap::addCell(MWWorld::CellStore *cell) { if (cell->isExterior()) - mCurrentGrid.emplace(cell->getCell()->getGridX(), cell->getCell()->getGridY()); + mExteriorSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())].needUpdate = true; +} + +void LocalMap::removeExteriorCell(int x, int y) +{ + mExteriorSegments.erase({ x, y }); } void LocalMap::removeCell(MWWorld::CellStore *cell) { saveFogOfWar(cell); - if (cell->isExterior()) - { - std::pair coords = std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()); - mSegments.erase(coords); - mCurrentGrid.erase(coords); - } - else - mSegments.clear(); + if (!cell->isExterior()) + mInteriorSegments.clear(); } osg::ref_ptr LocalMap::getMapTexture(int x, int y) { - SegmentMap::iterator found = mSegments.find(std::make_pair(x, y)); - if (found == mSegments.end()) + auto& segments(mInterior ? mInteriorSegments : mExteriorSegments); + SegmentMap::iterator found = segments.find(std::make_pair(x, y)); + if (found == segments.end()) return osg::ref_ptr(); else return found->second.mMapTexture; @@ -320,8 +305,9 @@ osg::ref_ptr LocalMap::getMapTexture(int x, int y) osg::ref_ptr LocalMap::getFogOfWarTexture(int x, int y) { - SegmentMap::iterator found = mSegments.find(std::make_pair(x, y)); - if (found == mSegments.end()) + auto& segments(mInterior ? mInteriorSegments : mExteriorSegments); + SegmentMap::iterator found = segments.find(std::make_pair(x, y)); + if (found == segments.end()) return osg::ref_ptr(); else return found->second.mFogOfWarTexture; @@ -371,7 +357,7 @@ void LocalMap::requestExteriorMap(const MWWorld::CellStore* cell) osg::Vec3d(0,1,0), zmin, zmax); setupRenderToTexture(camera, cell->getCell()->getGridX(), cell->getCell()->getGridY()); - MapSegment& segment = mSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())]; + MapSegment& segment = mExteriorSegments[std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())]; if (!segment.mFogOfWarImage) { if (cell->getFog()) @@ -512,7 +498,7 @@ void LocalMap::requestInteriorMap(const MWWorld::CellStore* cell) setupRenderToTexture(camera, x, y); auto coords = std::make_pair(x,y); - MapSegment& segment = mSegments[coords]; + MapSegment& segment = mInteriorSegments[coords]; if (!segment.mFogOfWarImage) { bool loaded = false; @@ -558,7 +544,8 @@ osg::Vec2f LocalMap::interiorMapToWorldPosition (float nX, float nY, int x, int bool LocalMap::isPositionExplored (float nX, float nY, int x, int y) { - const MapSegment& segment = mSegments[std::make_pair(x, y)]; + auto& segments(mInterior ? mInteriorSegments : mExteriorSegments); + const MapSegment& segment = segments[std::make_pair(x, y)]; if (!segment.mFogOfWarImage) return false; @@ -630,7 +617,8 @@ void LocalMap::updatePlayer (const osg::Vec3f& position, const osg::Quat& orient int texX = x + mx; int texY = y + my*-1; - MapSegment& segment = mSegments[std::make_pair(texX, texY)]; + auto& segments(mInterior ? mInteriorSegments : mExteriorSegments); + MapSegment& segment = segments[std::make_pair(texX, texY)]; if (!segment.mFogOfWarImage || !segment.mMapTexture) continue; diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index e586f8fb02..f9ccd5a011 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -50,6 +50,7 @@ namespace MWRender void requestMap (const MWWorld::CellStore* cell); void addCell(MWWorld::CellStore* cell); + void removeExteriorCell(int x, int y); void removeCell (MWWorld::CellStore* cell); @@ -126,13 +127,14 @@ namespace MWRender osg::ref_ptr mFogOfWarTexture; osg::ref_ptr mFogOfWarImage; - Grid mGrid; // the grid that was active at the time of rendering this segment + bool needUpdate = true; bool mHasFogState; }; typedef std::map, MapSegment> SegmentMap; - SegmentMap mSegments; + SegmentMap mExteriorSegments; + SegmentMap mInteriorSegments; int mMapResolution; diff --git a/docs/source/reference/modding/settings/map.rst b/docs/source/reference/modding/settings/map.rst index b0e30789ac..eeef0a1f39 100644 --- a/docs/source/reference/modding/settings/map.rst +++ b/docs/source/reference/modding/settings/map.rst @@ -114,3 +114,15 @@ allow zooming If this setting is true the user can zoom in/out on local and global map with the mouse wheel. This setting can be controlled in Advanced tab of the launcher. + +local viewing distance coef +--------------------------- + +:Type: float +:Range: > 0 and <= 1 +:Default: 0.5 + +This setting controls viewing distance on local map. It is the coefficient of the viewing distance viewable on the local map if 'distant terrain' is enabled otherwise you will see the default value (a 3x3 square centered on the player). +If view distance is changed in settings menu during the game, then viewable distance on the local map is not updated. + +This setting can not be configured except by editing the settings configuration file. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index c3c22c061c..36eca7f1ab 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -202,6 +202,9 @@ global = false # If true, allow zoom on local and global maps allow zooming = false +# The local view distance coefficient (1.0 is full view distance if distant terrain is enabled) +local viewing distance coef = 0.5 + [GUI] # Scales GUI window and widget size. (<1.0 is smaller, >1.0 is larger). From 18f5853279ddf8c0dfae0b58321fc703d6abb0b7 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Sun, 29 Nov 2020 22:03:16 +0100 Subject: [PATCH 6/9] [Global <-> Local] Auto switch between local and global map when zoom in/out --- apps/openmw/mwgui/mapwindow.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 9cc47e8c16..d4f63c0a26 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -886,16 +886,18 @@ namespace MWGui void MapWindow::onMapZoomed(MyGUI::Widget* sender, int rel) { const static int localWidgetSize = Settings::Manager::getInt("local map widget size", "Map"); + const static int globalCellSize = Settings::Manager::getInt("global map cell size", "Map"); const bool zoomOut = rel < 0; const bool zoomIn = !zoomOut; const double speedDiff = zoomOut ? 1.0 / speed : speed; const float localMapSizeInUnits = localWidgetSize * mNumCells; - const float currentMinLocalMapZoom = std::max( + const float currentMinLocalMapZoom = std::max({ + (float(globalCellSize) * 4.f) / float(localWidgetSize), float(mLocalMap->getWidth()) / localMapSizeInUnits, float(mLocalMap->getHeight()) / localMapSizeInUnits - ); + }); if (mGlobal) { @@ -910,6 +912,9 @@ namespace MWGui if (zoomIn && mGlobalMapZoom > 4.f) { mGlobalMapZoom = currentGlobalZoom; + mLocalMapZoom = currentMinLocalMapZoom; + onWorldButtonClicked(nullptr); + updateLocalMap(); return; //the zoom in is too big } @@ -933,7 +938,13 @@ namespace MWGui if (zoomOut && mLocalMapZoom < currentMinLocalMapZoom) { mLocalMapZoom = currentLocalZoom; - return; //the zoom out is too big + + float zoomRatio = 4.f/ mGlobalMapZoom; + mGlobalMapZoom = 4.f; + onWorldButtonClicked(nullptr); + + zoomOnCursor(zoomRatio); + return; //the zoom out is too big, we switch to the global map } } zoomOnCursor(speedDiff); From 9fee9dbc9cff147c48ec245cdfbd1092e611d7f2 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Sun, 29 Nov 2020 22:03:54 +0100 Subject: [PATCH 7/9] [Global map] Regroup markers when the zoom out --- apps/openmw/mwgui/mapwindow.cpp | 67 +++++++++++++++++++++++---------- apps/openmw/mwgui/mapwindow.hpp | 20 ++++++++-- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index d4f63c0a26..efb434d3bc 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -30,6 +30,8 @@ #include "confirmationdialog.hpp" #include "tooltips.hpp" +#include + namespace { @@ -976,8 +978,11 @@ namespace MWGui } setGlobalMapPlayerPosition(x, y); - for (auto& marker : mGlobalMapMarkers) - marker.second->setCoord(createMarkerCoords(marker.first.first, marker.first.second)); + for (auto& [marker, col] : mGlobalMapMarkers) + { + marker.widget->setCoord(createMarkerCoords(marker.position.x(), marker.position.y(), col.size())); + marker.widget->setVisible(marker.widget->getHeight() >= 6); + } } void MapWindow::onChangeScrollWindowCoord(MyGUI::Widget* sender) @@ -1016,12 +1021,12 @@ namespace MWGui setTitle("#{sCell=" + cellName + "}"); } - MyGUI::IntCoord MapWindow::createMarkerCoords(float x, float y) const + MyGUI::IntCoord MapWindow::createMarkerCoords(float x, float y, float agregatedWeight) const { float worldX, worldY; worldPosToGlobalMapImageSpace((x + 0.5f) * Constants::CellSizeInUnits, (y + 0.5f)* Constants::CellSizeInUnits, worldX, worldY); - const float markerSize = getMarkerSize(); + const float markerSize = getMarkerSize(agregatedWeight); const float halfMarkerSize = markerSize / 2.0f; return MyGUI::IntCoord( static_cast(worldX - halfMarkerSize), @@ -1029,13 +1034,12 @@ namespace MWGui markerSize, markerSize); } - MyGUI::Widget* MapWindow::createMarker(const std::string& name, float x, float y) + MyGUI::Widget* MapWindow::createMarker(const std::string& name, float x, float y, float agregatedWeight) { MyGUI::Widget* markerWidget = mGlobalMap->createWidget("MarkerButton", - createMarkerCoords(x, y), MyGUI::Align::Default); - + createMarkerCoords(x, y, agregatedWeight), MyGUI::Align::Default); + markerWidget->setVisible(markerWidget->getHeight() >= 6.0); markerWidget->setUserString("Caption_TextOneLine", "#{sCell=" + name + "}"); - setGlobalMapMarkerTooltip(markerWidget, x, y); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); @@ -1057,7 +1061,33 @@ namespace MWGui cell.second = y; if (mMarkers.insert(cell).second) { - mGlobalMapMarkers[std::make_pair(x, y)] = createMarker(name, x, y); + MapMarkerType mapMarkerWidget = { osg::Vec2f(x, y), createMarker(name, x, y, 0) }; + mGlobalMapMarkers.emplace(mapMarkerWidget, std::vector()); + + std::string name_ = name.substr(0, name.find(',')); + auto& entry = mGlobalMapMarkersByName[name_]; + if (!entry.widget) + { + entry = { osg::Vec2f(x, y), entry.widget }; //update the coords + + entry.widget = createMarker(name_, entry.position.x(), entry.position.y(), 1); + mGlobalMapMarkers.emplace(entry, std::vector{ entry }); + } + else + { + auto it = mGlobalMapMarkers.find(entry); + auto& marker = const_cast(it->first); + auto& elements = it->second; + elements.emplace_back(mapMarkerWidget); + + //we compute the barycenter of the entry elements => it will be the place on the world map for the agregated widget + marker.position = std::accumulate(elements.begin(), elements.end(), osg::Vec2f(0.f, 0.f), [](const auto& left, const auto& right) { + return left + right.position; + }) / float(elements.size()); + + marker.widget->setCoord(createMarkerCoords(marker.position.x(), marker.position.y(), elements.size())); + marker.widget->setVisible(marker.widget->getHeight() >= 6); + } } } @@ -1099,9 +1129,12 @@ namespace MWGui } } - float MapWindow::getMarkerSize() const + float MapWindow::getMarkerSize(size_t agregatedWeight) const { - return 12.0f * mGlobalMapZoom; + float markerSize = 12.f * mGlobalMapZoom; + if (mGlobalMapZoom < 1) + return markerSize * std::sqrt(agregatedWeight); //we want to see agregated object + return agregatedWeight ? 0 : markerSize; //we want to see only original markers (i.e. non agregated) } void MapWindow::resizeGlobalMap() @@ -1120,13 +1153,8 @@ namespace MWGui { LocalMapBase::updateCustomMarkers(); - for (auto& widgetPair : mGlobalMapMarkers) - { - int x = widgetPair.first.first; - int y = widgetPair.first.second; - MyGUI::Widget* markerWidget = widgetPair.second; - setGlobalMapMarkerTooltip(markerWidget, x, y); - } + for (auto& [widgetPair, ignore]: mGlobalMapMarkers) + setGlobalMapMarkerTooltip(widgetPair.widget, widgetPair.position.x(), widgetPair.position.y()); } void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) @@ -1251,8 +1279,9 @@ namespace MWGui mChanged = true; for (auto& widgetPair : mGlobalMapMarkers) - MyGUI::Gui::getInstance().destroyWidget(widgetPair.second); + MyGUI::Gui::getInstance().destroyWidget(widgetPair.first.widget); mGlobalMapMarkers.clear(); + mGlobalMapMarkersByName.clear(); } void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress) diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index f1d5d495fb..cb0d368b30 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -272,11 +272,12 @@ namespace MWGui void onChangeScrollWindowCoord(MyGUI::Widget* sender); void globalMapUpdatePlayer(); void setGlobalMapMarkerTooltip(MyGUI::Widget* widget, int x, int y); - float getMarkerSize() const; + float getMarkerSize(size_t agregatedWeight) const; void resizeGlobalMap(); void worldPosToGlobalMapImageSpace(float x, float z, float& imageX, float& imageY) const; - MyGUI::IntCoord createMarkerCoords(float x, float y) const; - MyGUI::Widget* createMarker(const std::string& name, float x, float y); + MyGUI::IntCoord createMarkerCoords(float x, float y, float agregatedWeight) const; + MyGUI::Widget* createMarker(const std::string& name, float x, float y, float agregatedWeight); + MyGUI::ScrollView* mGlobalMap; std::unique_ptr mGlobalMapTexture; @@ -301,7 +302,18 @@ namespace MWGui float mGlobalMapZoom = 1.0f; MWRender::GlobalMap* mGlobalMapRender; - std::map, MyGUI::Widget*> mGlobalMapMarkers; + struct MapMarkerType + { + osg::Vec2f position; + MyGUI::Widget* widget = nullptr; + + bool operator<(const MapMarkerType& right) const { + return widget < right.widget; + } + }; + + std::map mGlobalMapMarkersByName; + std::map> mGlobalMapMarkers; EditNoteDialog mEditNoteDialog; ESM::CustomMarker mEditingMarker; From a6f9e7274fdb3173bb6a45bc3e7722490ee67276 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Mon, 19 Oct 2020 22:48:37 +0200 Subject: [PATCH 8/9] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fccbba4ac9..526c6d9681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Bug #6174: Spellmaking and Enchanting sliders differences from vanilla Feature #2554: Modifying an object triggers the instances table to scroll to the corresponding record Feature #2780: A way to see current OpenMW version in the console + Feature #3616: Allow Zoom levels on the World Map Feature #5489: MCP: Telekinesis fix for activators Feature #5996: Support Lua scripts in OpenMW Feature #6017: Separate persistent and temporary cell references when saving From 1051745f29c161acb517b4bce734a17e1003e711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Sat, 24 Jul 2021 19:17:49 +0200 Subject: [PATCH 9/9] [Launcher] Add new setting 'allow zooming' to advanced tab in the launcher --- apps/launcher/advancedpage.cpp | 2 ++ files/ui/advancedpage.ui | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 00021268e3..2c33992ac3 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -192,6 +192,7 @@ bool Launcher::AdvancedPage::loadSettings() if (showOwnedIndex >= 0 && showOwnedIndex <= 3) showOwnedComboBox->setCurrentIndex(showOwnedIndex); loadSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI"); + loadSettingBool(useZoomOnMapCheckBox, "allow zooming", "Map"); loadSettingBool(graphicHerbalismCheckBox, "graphic herbalism", "Game"); scalingSpinBox->setValue(Settings::Manager::getFloat("scaling factor", "GUI")); } @@ -352,6 +353,7 @@ void Launcher::AdvancedPage::saveSettings() if (showOwnedCurrentIndex != Settings::Manager::getInt("show owned", "Game")) Settings::Manager::setInt("show owned", "Game", showOwnedCurrentIndex); saveSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI"); + saveSettingBool(useZoomOnMapCheckBox, "allow zooming", "Map"); saveSettingBool(graphicHerbalismCheckBox, "graphic herbalism", "Game"); float uiScalingFactor = scalingSpinBox->value(); if (uiScalingFactor != Settings::Manager::getFloat("scaling factor", "GUI")) diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index f72150df22..7964399319 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -1006,6 +1006,16 @@ True: In non-combat mode camera is positioned behind the character's shoulder. C + + + + <html><head/><body><p>Enable zooming on local and global maps.</p></body></html> + + + Can zoom on maps + + +