mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 11:39:44 +00:00
[Local map] Allow zoom on local map
This commit is contained in:
parent
9fadbd5b7a
commit
ed04ebe9ff
2 changed files with 100 additions and 14 deletions
|
@ -252,8 +252,8 @@ namespace MWGui
|
||||||
// normalized cell coordinates
|
// normalized cell coordinates
|
||||||
auto mapWidgetSize = getWidgetSize();
|
auto mapWidgetSize = getWidgetSize();
|
||||||
return MyGUI::IntPoint(
|
return MyGUI::IntPoint(
|
||||||
static_cast<int>(nX * mapWidgetSize + (mCellDistance + (cellX - mCurX)) * mapWidgetSize),
|
std::round(nX * mapWidgetSize + (mCellDistance + (cellX - mCurX)) * mapWidgetSize),
|
||||||
static_cast<int>(nY * mapWidgetSize + (mCellDistance - (cellY - mCurY)) * mapWidgetSize)
|
std::round(nY * mapWidgetSize + (mCellDistance - (cellY - mCurY)) * mapWidgetSize)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,6 +313,13 @@ namespace MWGui
|
||||||
mLocalMap->setViewOffset(viewOffset);
|
mLocalMap->setViewOffset(viewOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MyGUI::IntCoord LocalMapBase::getMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const
|
||||||
|
{
|
||||||
|
MarkerUserData& markerPos(*widget->getUserData<MarkerUserData>());
|
||||||
|
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()
|
void LocalMapBase::updateCustomMarkers()
|
||||||
{
|
{
|
||||||
for (MyGUI::Widget* widget : mCustomMarkerWidgets)
|
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.
|
// 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;
|
||||||
|
@ -400,7 +410,7 @@ namespace MWGui
|
||||||
|
|
||||||
float LocalMapBase::getWidgetSize() const
|
float LocalMapBase::getWidgetSize() const
|
||||||
{
|
{
|
||||||
return mMapWidgetSize;
|
return mLocalMapZoom * mMapWidgetSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny)
|
void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny)
|
||||||
|
@ -412,6 +422,11 @@ namespace MWGui
|
||||||
notifyPlayerUpdate ();
|
notifyPlayerUpdate ();
|
||||||
|
|
||||||
mCompass->setPosition(pos);
|
mCompass->setPosition(pos);
|
||||||
|
}
|
||||||
|
osg::Vec2f curPos((cellX + nx) * cellSize, (cellY + 1 - ny) * cellSize);
|
||||||
|
if ((curPos - mCurPos).length2() > 0.001)
|
||||||
|
{
|
||||||
|
mCurPos = curPos;
|
||||||
centerView();
|
centerView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,6 +484,7 @@ namespace MWGui
|
||||||
markerWidget->setImageTexture(markerTexture);
|
markerWidget->setImageTexture(markerTexture);
|
||||||
markerWidget->setImageCoord(MyGUI::IntCoord(0,0,8,8));
|
markerWidget->setImageCoord(MyGUI::IntCoord(0,0,8,8));
|
||||||
markerWidget->setNeedMouseFocus(false);
|
markerWidget->setNeedMouseFocus(false);
|
||||||
|
markerWidget->setUserData(markerPos);
|
||||||
mMagicMarkerWidgets.push_back(markerWidget);
|
mMagicMarkerWidgets.push_back(markerWidget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -619,12 +635,40 @@ namespace MWGui
|
||||||
markerWidget->setDepth(Local_MarkerAboveFogLayer);
|
markerWidget->setDepth(Local_MarkerAboveFogLayer);
|
||||||
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
|
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
|
||||||
markerWidget->setNeedMouseFocus(false);
|
markerWidget->setNeedMouseFocus(false);
|
||||||
|
markerWidget->setUserData(markerPos);
|
||||||
mMagicMarkerWidgets.push_back(markerWidget);
|
mMagicMarkerWidgets.push_back(markerWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw();
|
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<ESM::CustomMarker>();
|
||||||
|
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)
|
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->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
|
||||||
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
||||||
mEventBoxLocal->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onMapDoubleClicked);
|
mEventBoxLocal->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onMapDoubleClicked);
|
||||||
|
mEventBoxLocal->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed);
|
||||||
|
|
||||||
LocalMapBase::init(mLocalMap, mPlayerArrowLocal);
|
LocalMapBase::init(mLocalMap, mPlayerArrowLocal);
|
||||||
|
|
||||||
|
@ -772,9 +817,17 @@ namespace MWGui
|
||||||
|
|
||||||
void MapWindow::onMapZoomed(MyGUI::Widget* sender, int rel)
|
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 zoomOut = rel < 0;
|
||||||
const bool zoomIn = !zoomOut;
|
const bool zoomIn = !zoomOut;
|
||||||
const double speedDiff = zoomOut ? 1.0 / speed : speed;
|
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)
|
if (mGlobal)
|
||||||
{
|
{
|
||||||
|
@ -797,16 +850,36 @@ namespace MWGui
|
||||||
mGlobalMapZoom = currentGlobalZoom;
|
mGlobalMapZoom = currentGlobalZoom;
|
||||||
return; //the zoom out is too big, we have reach the borders of the widget
|
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)
|
void MapWindow::zoomOnCursor(float speedDiff)
|
||||||
{
|
{
|
||||||
auto cursor = MyGUI::InputManager::getInstance().getMousePosition() - mGlobalMap->getAbsolutePosition();
|
auto map = mGlobal ? mGlobalMap : mLocalMap;
|
||||||
auto centerView = mGlobalMap->getViewOffset() - cursor;
|
auto cursor = MyGUI::InputManager::getInstance().getMousePosition() - map->getAbsolutePosition();
|
||||||
updateGlobalMap();
|
auto centerView = map->getViewOffset() - cursor;
|
||||||
mGlobalMap->setViewOffset(MyGUI::IntPoint(
|
|
||||||
|
mGlobal? updateGlobalMap() : updateLocalMap();
|
||||||
|
|
||||||
|
map->setViewOffset(MyGUI::IntPoint(
|
||||||
std::round(centerView.left * speedDiff) + cursor.left,
|
std::round(centerView.left * speedDiff) + cursor.left,
|
||||||
std::round(centerView.top * speedDiff) + cursor.top
|
std::round(centerView.top * speedDiff) + cursor.top
|
||||||
));
|
));
|
||||||
|
@ -815,7 +888,14 @@ namespace MWGui
|
||||||
void MapWindow::updateGlobalMap()
|
void MapWindow::updateGlobalMap()
|
||||||
{
|
{
|
||||||
resizeGlobalMap();
|
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)
|
for (auto& marker : mGlobalMapMarkers)
|
||||||
marker.second->setCoord(createMarkerCoords(marker.first.first, marker.first.second));
|
marker.second->setCoord(createMarkerCoords(marker.first.first, marker.first.second));
|
||||||
|
@ -1043,6 +1123,7 @@ namespace MWGui
|
||||||
|
|
||||||
void MapWindow::centerView()
|
void MapWindow::centerView()
|
||||||
{
|
{
|
||||||
|
LocalMapBase::centerView();
|
||||||
// set the view offset so that player is in the center
|
// set the view offset so that player is in the center
|
||||||
MyGUI::IntSize viewsize = mGlobalMap->getSize();
|
MyGUI::IntSize viewsize = mGlobalMap->getSize();
|
||||||
MyGUI::IntPoint pos = mPlayerArrowGlobal->getPosition() + MyGUI::IntPoint{ 16,16 };
|
MyGUI::IntPoint pos = mPlayerArrowGlobal->getPosition() + MyGUI::IntPoint{ 16,16 };
|
||||||
|
@ -1055,8 +1136,6 @@ namespace MWGui
|
||||||
float x, y;
|
float x, y;
|
||||||
worldPosToGlobalMapImageSpace(worldX, worldY, x, y);
|
worldPosToGlobalMapImageSpace(worldX, worldY, x, y);
|
||||||
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(static_cast<int>(x - 16), static_cast<int>(y - 16)));
|
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(static_cast<int>(x - 16), static_cast<int>(y - 16)));
|
||||||
|
|
||||||
centerView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::setGlobalMapPlayerDir(const float x, const float y)
|
void MapWindow::setGlobalMapPlayerDir(const float x, const float y)
|
||||||
|
@ -1141,12 +1220,14 @@ namespace MWGui
|
||||||
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
|
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
|
||||||
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
||||||
marker->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onCustomMarkerDoubleClicked);
|
marker->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onCustomMarkerDoubleClicked);
|
||||||
|
marker->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::doorMarkerCreated(MyGUI::Widget *marker)
|
void MapWindow::doorMarkerCreated(MyGUI::Widget *marker)
|
||||||
{
|
{
|
||||||
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
|
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
|
||||||
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
||||||
|
marker->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
|
@ -107,9 +107,13 @@ namespace MWGui
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void updateLocalMap();
|
||||||
|
|
||||||
|
float mLocalMapZoom = 1.f;
|
||||||
MWRender::LocalMap* mLocalMapRender;
|
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;
|
bool mInterior;
|
||||||
MyGUI::ScrollView* mLocalMap;
|
MyGUI::ScrollView* mLocalMap;
|
||||||
MyGUI::ImageBox* mCompass;
|
MyGUI::ImageBox* mCompass;
|
||||||
|
@ -153,9 +157,10 @@ 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(float worldX, float worldY, MarkerUserData& markerPos, size_t markerSize) 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::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() {}
|
virtual void notifyPlayerUpdate() {}
|
||||||
void centerView();
|
virtual void centerView();
|
||||||
virtual void notifyMapChanged() {}
|
virtual void notifyMapChanged() {}
|
||||||
|
|
||||||
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
|
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
|
||||||
|
@ -302,7 +307,7 @@ namespace MWGui
|
||||||
|
|
||||||
void notifyPlayerUpdate() override;
|
void notifyPlayerUpdate() override;
|
||||||
|
|
||||||
void centerView();
|
void centerView() override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue