mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-06 00:55:50 +00:00
343 lines
10 KiB
C++
343 lines
10 KiB
C++
#ifndef MWGUI_MAPWINDOW_H
|
|
#define MWGUI_MAPWINDOW_H
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
#include <osg/Vec2f>
|
|
|
|
#include <MyGUI_ITexture.h>
|
|
|
|
#include "windowpinnablebase.hpp"
|
|
|
|
#include <components/esm3/custommarkerstate.hpp>
|
|
#include <components/misc/constants.hpp>
|
|
|
|
namespace MWRender
|
|
{
|
|
class GlobalMap;
|
|
class LocalMap;
|
|
}
|
|
|
|
namespace ESM
|
|
{
|
|
class ESMReader;
|
|
class ESMWriter;
|
|
}
|
|
|
|
namespace MWWorld
|
|
{
|
|
class CellStore;
|
|
}
|
|
|
|
namespace Loading
|
|
{
|
|
class Listener;
|
|
}
|
|
|
|
namespace SceneUtil
|
|
{
|
|
class WorkQueue;
|
|
}
|
|
|
|
namespace MWGui
|
|
{
|
|
|
|
class CustomMarkerCollection
|
|
{
|
|
public:
|
|
void addMarker(const ESM::CustomMarker& marker, bool triggerEvent = true);
|
|
void deleteMarker(const ESM::CustomMarker& marker);
|
|
void updateMarker(const ESM::CustomMarker& marker, const std::string& newNote);
|
|
|
|
void clear();
|
|
|
|
size_t size() const;
|
|
|
|
typedef std::multimap<ESM::RefId, ESM::CustomMarker> ContainerType;
|
|
|
|
typedef std::pair<ContainerType::const_iterator, ContainerType::const_iterator> RangeType;
|
|
|
|
ContainerType::const_iterator begin() const;
|
|
ContainerType::const_iterator end() const;
|
|
|
|
RangeType getMarkers(const ESM::RefId& cellId) const;
|
|
|
|
typedef MyGUI::delegates::MultiDelegate<> EventHandle_Void;
|
|
EventHandle_Void eventMarkersChanged;
|
|
|
|
private:
|
|
ContainerType mMarkers;
|
|
};
|
|
|
|
class LocalMapBase
|
|
{
|
|
public:
|
|
LocalMapBase(CustomMarkerCollection& markers, MWRender::LocalMap* localMapRender, bool fogOfWarEnabled);
|
|
virtual ~LocalMapBase();
|
|
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);
|
|
void requestMapRender(const MWWorld::CellStore* cell);
|
|
void setPlayerDir(const float x, const float y);
|
|
void setPlayerPos(int cellX, int cellY, const float nx, const float ny);
|
|
|
|
void onFrame(float dt);
|
|
|
|
bool toggleFogOfWar();
|
|
|
|
struct MarkerUserData
|
|
{
|
|
MarkerUserData(MWRender::LocalMap* map)
|
|
: mLocalMapRender(map)
|
|
, cellX(0)
|
|
, cellY(0)
|
|
, nX(0.f)
|
|
, nY(0.f)
|
|
{
|
|
}
|
|
|
|
bool isPositionExplored() const;
|
|
|
|
MWRender::LocalMap* mLocalMapRender;
|
|
int cellX;
|
|
int cellY;
|
|
float nX;
|
|
float nY;
|
|
std::vector<std::string> notes;
|
|
std::string caption;
|
|
};
|
|
|
|
protected:
|
|
void updateLocalMap();
|
|
|
|
float mLocalMapZoom = 1.f;
|
|
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;
|
|
std::string mPrefix;
|
|
bool mChanged;
|
|
bool mFogOfWarToggled;
|
|
bool mFogOfWarEnabled;
|
|
|
|
int mNumCells; // for convenience, mCellDistance * 2 + 1
|
|
int mCellDistance;
|
|
|
|
// Stores markers that were placed by a player. May be shared between multiple map views.
|
|
CustomMarkerCollection& mCustomMarkers;
|
|
|
|
struct MapEntry
|
|
{
|
|
MapEntry(MyGUI::ImageBox* mapWidget, MyGUI::ImageBox* fogWidget)
|
|
: mMapWidget(mapWidget)
|
|
, mFogWidget(fogWidget)
|
|
, mCellX(0)
|
|
, mCellY(0)
|
|
{
|
|
}
|
|
|
|
MyGUI::ImageBox* mMapWidget;
|
|
MyGUI::ImageBox* mFogWidget;
|
|
std::unique_ptr<MyGUI::ITexture> mMapTexture;
|
|
std::unique_ptr<MyGUI::ITexture> mFogTexture;
|
|
int mCellX;
|
|
int mCellY;
|
|
};
|
|
std::vector<MapEntry> mMaps;
|
|
|
|
// Keep track of created marker widgets, just to easily remove them later.
|
|
std::vector<MyGUI::Widget*> mExteriorDoorMarkerWidgets;
|
|
std::map<std::pair<int, int>, std::vector<MyGUI::Widget*>> mExteriorDoorsByCell;
|
|
std::vector<MyGUI::Widget*> mInteriorDoorMarkerWidgets;
|
|
std::vector<MyGUI::Widget*> mMagicMarkerWidgets;
|
|
std::vector<MyGUI::Widget*> mCustomMarkerWidgets;
|
|
std::vector<MyGUI::Widget*> mDoorMarkersToRecycle;
|
|
|
|
std::vector<MyGUI::Widget*>& currentDoorMarkersWidgets();
|
|
|
|
virtual void updateCustomMarkers();
|
|
|
|
void applyFogOfWar();
|
|
|
|
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;
|
|
MyGUI::IntCoord getMarkerCoordinates(MyGUI::Widget* widget, size_t markerSize) const;
|
|
|
|
virtual void notifyPlayerUpdate() {}
|
|
virtual void centerView();
|
|
virtual void notifyMapChanged() {}
|
|
|
|
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
|
|
virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
|
|
|
|
void updateRequiredMaps();
|
|
|
|
void updateMagicMarkers();
|
|
void addDetectionMarkers(int type);
|
|
|
|
void redraw();
|
|
float getWidgetSize() const;
|
|
|
|
float mMarkerUpdateTimer;
|
|
|
|
float mLastDirectionX;
|
|
float mLastDirectionY;
|
|
|
|
bool mNeedDoorMarkersUpdate;
|
|
|
|
private:
|
|
void updateDoorMarkers();
|
|
};
|
|
|
|
class EditNoteDialog : public MWGui::WindowModal
|
|
{
|
|
public:
|
|
EditNoteDialog();
|
|
|
|
void onOpen() override;
|
|
|
|
void showDeleteButton(bool show);
|
|
bool getDeleteButtonShown();
|
|
void setText(const std::string& text);
|
|
std::string getText();
|
|
|
|
typedef MyGUI::delegates::MultiDelegate<> EventHandle_Void;
|
|
|
|
EventHandle_Void eventDeleteClicked;
|
|
EventHandle_Void eventOkClicked;
|
|
|
|
private:
|
|
void onCancelButtonClicked(MyGUI::Widget* sender);
|
|
void onOkButtonClicked(MyGUI::Widget* sender);
|
|
void onDeleteButtonClicked(MyGUI::Widget* sender);
|
|
|
|
MyGUI::TextBox* mTextEdit;
|
|
MyGUI::Button* mOkButton;
|
|
MyGUI::Button* mCancelButton;
|
|
MyGUI::Button* mDeleteButton;
|
|
};
|
|
|
|
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop
|
|
{
|
|
public:
|
|
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender,
|
|
SceneUtil::WorkQueue* workQueue);
|
|
virtual ~MapWindow();
|
|
|
|
void setCellName(const std::string& cellName);
|
|
|
|
void setAlpha(float alpha) override;
|
|
void setVisible(bool visible) override;
|
|
|
|
void renderGlobalMap();
|
|
|
|
/// adds the marker to the global map
|
|
/// @param name The ESM::Cell::mName
|
|
void addVisitedLocation(const std::string& name, int x, int y);
|
|
|
|
// reveals this cell's map on the global map
|
|
void cellExplored(int x, int y);
|
|
|
|
void setGlobalMapPlayerPosition(float worldX, float worldY);
|
|
void setGlobalMapPlayerDir(const float x, const float y);
|
|
|
|
void ensureGlobalMapLoaded();
|
|
|
|
void onOpen() override;
|
|
|
|
void onFrame(float dt) override;
|
|
|
|
void updateCustomMarkers() override;
|
|
|
|
/// Clear all savegame-specific data
|
|
void clear() override;
|
|
|
|
void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
|
void readRecord(ESM::ESMReader& reader, uint32_t type);
|
|
|
|
void asyncPrepareSaveMap();
|
|
|
|
std::string_view getWindowIdForLua() const override { return "Map"; }
|
|
|
|
private:
|
|
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
|
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();
|
|
void onNoteEditDeleteConfirm();
|
|
void onNoteDoubleClicked(MyGUI::Widget* sender);
|
|
void onChangeScrollWindowCoord(MyGUI::Widget* sender);
|
|
void globalMapUpdatePlayer();
|
|
void setGlobalMapMarkerTooltip(MyGUI::Widget* widget, int x, int y);
|
|
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, float agregatedWeight) const;
|
|
MyGUI::Widget* createMarker(const std::string& name, float x, float y, float agregatedWeight);
|
|
|
|
MyGUI::ScrollView* mGlobalMap;
|
|
std::unique_ptr<MyGUI::ITexture> mGlobalMapTexture;
|
|
std::unique_ptr<MyGUI::ITexture> mGlobalMapOverlayTexture;
|
|
MyGUI::ImageBox* mGlobalMapImage;
|
|
MyGUI::ImageBox* mGlobalMapOverlay;
|
|
MyGUI::ImageBox* mPlayerArrowLocal;
|
|
MyGUI::ImageBox* mPlayerArrowGlobal;
|
|
MyGUI::Button* mButton;
|
|
MyGUI::IntPoint mLastDragPos;
|
|
|
|
MyGUI::IntCoord mLastScrollWindowCoordinates;
|
|
|
|
// Markers on global map
|
|
typedef std::pair<int, int> CellId;
|
|
std::set<CellId> mMarkers;
|
|
|
|
MyGUI::Button* mEventBoxGlobal;
|
|
MyGUI::Button* mEventBoxLocal;
|
|
|
|
float mGlobalMapZoom = 1.0f;
|
|
std::unique_ptr<MWRender::GlobalMap> mGlobalMapRender;
|
|
|
|
struct MapMarkerType
|
|
{
|
|
osg::Vec2f position;
|
|
MyGUI::Widget* widget = nullptr;
|
|
|
|
bool operator<(const MapMarkerType& right) const { return widget < right.widget; }
|
|
};
|
|
|
|
std::map<std::string, MapMarkerType> mGlobalMapMarkersByName;
|
|
std::map<MapMarkerType, std::vector<MapMarkerType>> mGlobalMapMarkers;
|
|
|
|
EditNoteDialog mEditNoteDialog;
|
|
ESM::CustomMarker mEditingMarker;
|
|
|
|
void onPinToggled() override;
|
|
void onTitleDoubleClicked() override;
|
|
|
|
void doorMarkerCreated(MyGUI::Widget* marker) override;
|
|
void customMarkerCreated(MyGUI::Widget* marker) override;
|
|
|
|
void notifyPlayerUpdate() override;
|
|
|
|
void centerView() override;
|
|
};
|
|
}
|
|
#endif
|