1 #include "mapwindow.hpp"
2 
3 #include <osg/Texture2D>
4 
5 #include <MyGUI_ScrollView.h>
6 #include <MyGUI_ImageBox.h>
7 #include <MyGUI_RenderManager.h>
8 #include <MyGUI_Gui.h>
9 #include <MyGUI_LanguageManager.h>
10 #include <MyGUI_InputManager.h>
11 #include <MyGUI_RotatingSkin.h>
12 #include <MyGUI_FactoryManager.h>
13 
14 #include <components/esm/globalmap.hpp>
15 #include <components/esm/esmwriter.hpp>
16 #include <components/settings/settings.hpp>
17 #include <components/myguiplatform/myguitexture.hpp>
18 
19 #include "../mwbase/windowmanager.hpp"
20 #include "../mwbase/world.hpp"
21 #include "../mwbase/environment.hpp"
22 
23 #include "../mwworld/player.hpp"
24 #include "../mwworld/cellstore.hpp"
25 #include "../mwworld/esmstore.hpp"
26 
27 #include "../mwrender/globalmap.hpp"
28 #include "../mwrender/localmap.hpp"
29 
30 #include "confirmationdialog.hpp"
31 #include "tooltips.hpp"
32 
33 namespace
34 {
35 
36     const int cellSize = Constants::CellSizeInUnits;
37 
38     enum LocalMapWidgetDepth
39     {
40         Local_MarkerAboveFogLayer = 0,
41         Local_CompassLayer = 1,
42         Local_FogLayer = 2,
43         Local_MarkerLayer = 3,
44         Local_MapLayer = 4
45     };
46 
47     enum GlobalMapWidgetDepth
48     {
49         Global_CompassLayer = 0,
50         Global_MarkerLayer = 1,
51         Global_ExploreOverlayLayer = 2,
52         Global_MapLayer = 3
53     };
54 
55 
56     /// @brief A widget that changes its color when hovered.
57     class MarkerWidget final : public MyGUI::Widget
58     {
59         MYGUI_RTTI_DERIVED(MarkerWidget)
60 
61     public:
setNormalColour(const MyGUI::Colour & colour)62         void setNormalColour(const MyGUI::Colour& colour)
63         {
64             mNormalColour = colour;
65             setColour(colour);
66         }
67 
setHoverColour(const MyGUI::Colour & colour)68         void setHoverColour(const MyGUI::Colour& colour)
69         {
70             mHoverColour = colour;
71         }
72 
73     private:
74         MyGUI::Colour mNormalColour;
75         MyGUI::Colour mHoverColour;
76 
onMouseLostFocus(MyGUI::Widget * _new)77         void onMouseLostFocus(MyGUI::Widget* _new) override
78         {
79             setColour(mNormalColour);
80         }
81 
onMouseSetFocus(MyGUI::Widget * _old)82         void onMouseSetFocus(MyGUI::Widget* _old) override
83         {
84             setColour(mHoverColour);
85         }
86     };
87 }
88 
89 namespace MWGui
90 {
91 
addMarker(const ESM::CustomMarker & marker,bool triggerEvent)92     void CustomMarkerCollection::addMarker(const ESM::CustomMarker &marker, bool triggerEvent)
93     {
94         mMarkers.insert(std::make_pair(marker.mCell, marker));
95         if (triggerEvent)
96             eventMarkersChanged();
97     }
98 
deleteMarker(const ESM::CustomMarker & marker)99     void CustomMarkerCollection::deleteMarker(const ESM::CustomMarker &marker)
100     {
101         std::pair<ContainerType::iterator, ContainerType::iterator> range = mMarkers.equal_range(marker.mCell);
102 
103         for (ContainerType::iterator it = range.first; it != range.second; ++it)
104         {
105             if (it->second == marker)
106             {
107                 mMarkers.erase(it);
108                 eventMarkersChanged();
109                 return;
110             }
111         }
112         throw std::runtime_error("can't find marker to delete");
113     }
114 
updateMarker(const ESM::CustomMarker & marker,const std::string & newNote)115     void CustomMarkerCollection::updateMarker(const ESM::CustomMarker &marker, const std::string &newNote)
116     {
117         std::pair<ContainerType::iterator, ContainerType::iterator> range = mMarkers.equal_range(marker.mCell);
118 
119         for (ContainerType::iterator it = range.first; it != range.second; ++it)
120         {
121             if (it->second == marker)
122             {
123                 it->second.mNote = newNote;
124                 eventMarkersChanged();
125                 return;
126             }
127         }
128         throw std::runtime_error("can't find marker to update");
129     }
130 
clear()131     void CustomMarkerCollection::clear()
132     {
133         mMarkers.clear();
134         eventMarkersChanged();
135     }
136 
begin() const137     CustomMarkerCollection::ContainerType::const_iterator CustomMarkerCollection::begin() const
138     {
139         return mMarkers.begin();
140     }
141 
end() const142     CustomMarkerCollection::ContainerType::const_iterator CustomMarkerCollection::end() const
143     {
144         return mMarkers.end();
145     }
146 
getMarkers(const ESM::CellId & cellId) const147     CustomMarkerCollection::RangeType CustomMarkerCollection::getMarkers(const ESM::CellId &cellId) const
148     {
149         return mMarkers.equal_range(cellId);
150     }
151 
size() const152     size_t CustomMarkerCollection::size() const
153     {
154         return mMarkers.size();
155     }
156 
157     // ------------------------------------------------------
158 
LocalMapBase(CustomMarkerCollection & markers,MWRender::LocalMap * localMapRender,bool fogOfWarEnabled)159     LocalMapBase::LocalMapBase(CustomMarkerCollection &markers, MWRender::LocalMap* localMapRender, bool fogOfWarEnabled)
160         : mLocalMapRender(localMapRender)
161         , mCurX(0)
162         , mCurY(0)
163         , mInterior(false)
164         , mLocalMap(nullptr)
165         , mCompass(nullptr)
166         , mChanged(true)
167         , mFogOfWarToggled(true)
168         , mFogOfWarEnabled(fogOfWarEnabled)
169         , mMapWidgetSize(0)
170         , mNumCells(0)
171         , mCellDistance(0)
172         , mCustomMarkers(markers)
173         , mMarkerUpdateTimer(0.0f)
174         , mLastDirectionX(0.0f)
175         , mLastDirectionY(0.0f)
176         , mNeedDoorMarkersUpdate(false)
177     {
178         mCustomMarkers.eventMarkersChanged += MyGUI::newDelegate(this, &LocalMapBase::updateCustomMarkers);
179     }
180 
~LocalMapBase()181     LocalMapBase::~LocalMapBase()
182     {
183         mCustomMarkers.eventMarkersChanged -= MyGUI::newDelegate(this, &LocalMapBase::updateCustomMarkers);
184     }
185 
init(MyGUI::ScrollView * widget,MyGUI::ImageBox * compass)186     void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass)
187     {
188         mLocalMap = widget;
189         mCompass = compass;
190         mMapWidgetSize = std::max(1, Settings::Manager::getInt("local map widget size", "Map"));
191         mCellDistance = Constants::CellGridRadius;
192         mNumCells = mCellDistance * 2 + 1;
193 
194         mLocalMap->setCanvasSize(mMapWidgetSize*mNumCells, mMapWidgetSize*mNumCells);
195 
196         mCompass->setDepth(Local_CompassLayer);
197         mCompass->setNeedMouseFocus(false);
198 
199         for (int mx=0; mx<mNumCells; ++mx)
200         {
201             for (int my=0; my<mNumCells; ++my)
202             {
203                 MyGUI::ImageBox* map = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
204                     MyGUI::IntCoord(mx*mMapWidgetSize, my*mMapWidgetSize, mMapWidgetSize, mMapWidgetSize),
205                     MyGUI::Align::Top | MyGUI::Align::Left);
206                 map->setDepth(Local_MapLayer);
207 
208                 MyGUI::ImageBox* fog = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
209                     MyGUI::IntCoord(mx*mMapWidgetSize, my*mMapWidgetSize, mMapWidgetSize, mMapWidgetSize),
210                     MyGUI::Align::Top | MyGUI::Align::Left);
211                 fog->setDepth(Local_FogLayer);
212                 fog->setColour(MyGUI::Colour(0, 0, 0));
213 
214                 map->setNeedMouseFocus(false);
215                 fog->setNeedMouseFocus(false);
216 
217                 mMaps.emplace_back(map, fog);
218             }
219         }
220     }
221 
setCellPrefix(const std::string & prefix)222     void LocalMapBase::setCellPrefix(const std::string& prefix)
223     {
224         mPrefix = prefix;
225         mChanged = true;
226     }
227 
toggleFogOfWar()228     bool LocalMapBase::toggleFogOfWar()
229     {
230         mFogOfWarToggled = !mFogOfWarToggled;
231         applyFogOfWar();
232         return mFogOfWarToggled;
233     }
234 
applyFogOfWar()235     void LocalMapBase::applyFogOfWar()
236     {
237         for (int mx=0; mx<mNumCells; ++mx)
238         {
239             for (int my=0; my<mNumCells; ++my)
240             {
241                 MapEntry& entry = mMaps[my + mNumCells*mx];
242                 MyGUI::ImageBox* fog = entry.mFogWidget;
243 
244                 if (!mFogOfWarToggled || !mFogOfWarEnabled)
245                 {
246                     fog->setImageTexture("");
247                     entry.mFogTexture.reset();
248                     continue;
249                 }
250             }
251         }
252 
253         redraw();
254     }
255 
getMarkerPosition(float worldX,float worldY,MarkerUserData & markerPos)256     MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos)
257     {
258         MyGUI::IntPoint widgetPos;
259         // normalized cell coordinates
260         float nX,nY;
261 
262         if (!mInterior)
263         {
264             int cellX, cellY;
265             MWBase::Environment::get().getWorld()->positionToIndex(worldX, worldY, cellX, cellY);
266             nX = (worldX - cellSize * cellX) / cellSize;
267             // Image space is -Y up, cells are Y up
268             nY = 1 - (worldY - cellSize * cellY) / cellSize;
269 
270             float cellDx = static_cast<float>(cellX - mCurX);
271             float cellDy = static_cast<float>(cellY - mCurY);
272 
273             markerPos.cellX = cellX;
274             markerPos.cellY = cellY;
275 
276             widgetPos = MyGUI::IntPoint(static_cast<int>(nX * mMapWidgetSize + (mCellDistance + cellDx) * mMapWidgetSize),
277                                         static_cast<int>(nY * mMapWidgetSize + (mCellDistance - cellDy) * mMapWidgetSize));
278         }
279         else
280         {
281             int cellX, cellY;
282             osg::Vec2f worldPos (worldX, worldY);
283             mLocalMapRender->worldToInteriorMapPosition(worldPos, nX, nY, cellX, cellY);
284 
285             markerPos.cellX = cellX;
286             markerPos.cellY = cellY;
287 
288             // Image space is -Y up, cells are Y up
289             widgetPos = MyGUI::IntPoint(static_cast<int>(nX * mMapWidgetSize + (mCellDistance + (cellX - mCurX)) * mMapWidgetSize),
290                                         static_cast<int>(nY * mMapWidgetSize + (mCellDistance - (cellY - mCurY)) * mMapWidgetSize));
291         }
292 
293         markerPos.nX = nX;
294         markerPos.nY = nY;
295         return widgetPos;
296     }
297 
updateCustomMarkers()298     void LocalMapBase::updateCustomMarkers()
299     {
300         for (MyGUI::Widget* widget : mCustomMarkerWidgets)
301             MyGUI::Gui::getInstance().destroyWidget(widget);
302         mCustomMarkerWidgets.clear();
303 
304         for (int dX = -mCellDistance; dX <= mCellDistance; ++dX)
305         {
306             for (int dY =-mCellDistance; dY <= mCellDistance; ++dY)
307             {
308                 ESM::CellId cellId;
309                 cellId.mPaged = !mInterior;
310                 cellId.mWorldspace = (mInterior ? mPrefix : ESM::CellId::sDefaultWorldspace);
311                 cellId.mIndex.mX = mCurX+dX;
312                 cellId.mIndex.mY = mCurY+dY;
313 
314                 CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(cellId);
315                 for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second; ++it)
316                 {
317                     const ESM::CustomMarker& marker = it->second;
318 
319                     MarkerUserData markerPos (mLocalMapRender);
320                     MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos);
321 
322                     MyGUI::IntCoord widgetCoord(widgetPos.left - 8,
323                                                 widgetPos.top - 8,
324                                                 16, 16);
325                     MarkerWidget* markerWidget = mLocalMap->createWidget<MarkerWidget>("CustomMarkerButton",
326                         widgetCoord, MyGUI::Align::Default);
327                     markerWidget->setDepth(Local_MarkerAboveFogLayer);
328                     markerWidget->setUserString("ToolTipType", "Layout");
329                     markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
330                     markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote));
331                     markerWidget->setNormalColour(MyGUI::Colour(0.6f, 0.6f, 0.6f));
332                     markerWidget->setHoverColour(MyGUI::Colour(1.0f, 1.0f, 1.0f));
333                     markerWidget->setUserData(marker);
334                     markerWidget->setNeedMouseFocus(true);
335                     customMarkerCreated(markerWidget);
336                     mCustomMarkerWidgets.push_back(markerWidget);
337                 }
338             }
339         }
340 
341         redraw();
342     }
343 
setActiveCell(const int x,const int y,bool interior)344     void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
345     {
346         if (x==mCurX && y==mCurY && mInterior==interior && !mChanged)
347             return; // don't do anything if we're still in the same cell
348 
349         mCurX = x;
350         mCurY = y;
351         mInterior = interior;
352         mChanged = false;
353 
354         for (int mx=0; mx<mNumCells; ++mx)
355         {
356             for (int my=0; my<mNumCells; ++my)
357             {
358                 MapEntry& entry = mMaps[my + mNumCells*mx];
359                 entry.mMapWidget->setRenderItemTexture(nullptr);
360                 entry.mFogWidget->setRenderItemTexture(nullptr);
361                 entry.mMapTexture.reset();
362                 entry.mFogTexture.reset();
363 
364                 entry.mCellX = x + (mx - mCellDistance);
365                 entry.mCellY = y - (my - mCellDistance);
366             }
367         }
368 
369         // Delay the door markers update until scripts have been given a chance to run.
370         // If we don't do this, door markers that should be disabled will still appear on the map.
371         mNeedDoorMarkersUpdate = true;
372 
373         updateMagicMarkers();
374         updateCustomMarkers();
375     }
376 
requestMapRender(const MWWorld::CellStore * cell)377     void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell)
378     {
379         mLocalMapRender->requestMap(cell);
380     }
381 
redraw()382     void LocalMapBase::redraw()
383     {
384         // Redraw children in proper order
385         mLocalMap->getParent()->_updateChilds();
386     }
387 
setPlayerPos(int cellX,int cellY,const float nx,const float ny)388     void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny)
389     {
390         MyGUI::IntPoint pos(static_cast<int>(mMapWidgetSize * mCellDistance + nx*mMapWidgetSize - 16), static_cast<int>(mMapWidgetSize * mCellDistance + ny*mMapWidgetSize - 16));
391         pos.left += (cellX - mCurX) * mMapWidgetSize;
392         pos.top -= (cellY - mCurY) * mMapWidgetSize;
393 
394         if (pos != mCompass->getPosition())
395         {
396             notifyPlayerUpdate ();
397 
398             mCompass->setPosition(pos);
399             MyGUI::IntPoint middle (pos.left+16, pos.top+16);
400                     MyGUI::IntCoord viewsize = mLocalMap->getCoord();
401             MyGUI::IntPoint viewOffset((viewsize.width / 2) - middle.left, (viewsize.height / 2) - middle.top);
402             mLocalMap->setViewOffset(viewOffset);
403         }
404     }
405 
setPlayerDir(const float x,const float y)406     void LocalMapBase::setPlayerDir(const float x, const float y)
407     {
408         if (x == mLastDirectionX && y == mLastDirectionY)
409             return;
410 
411         notifyPlayerUpdate ();
412 
413         MyGUI::ISubWidget* main = mCompass->getSubWidgetMain();
414         MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
415         rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
416         float angle = std::atan2(x,y);
417         rotatingSubskin->setAngle(angle);
418 
419         mLastDirectionX = x;
420         mLastDirectionY = y;
421     }
422 
addDetectionMarkers(int type)423     void LocalMapBase::addDetectionMarkers(int type)
424     {
425         std::vector<MWWorld::Ptr> markers;
426         MWBase::World* world = MWBase::Environment::get().getWorld();
427         world->listDetectedReferences(
428                     world->getPlayerPtr(),
429                     markers, MWBase::World::DetectionType(type));
430         if (markers.empty())
431             return;
432 
433         std::string markerTexture;
434         if (type == MWBase::World::Detect_Creature)
435         {
436             markerTexture = "textures\\detect_animal_icon.dds";
437         }
438         if (type == MWBase::World::Detect_Key)
439         {
440             markerTexture = "textures\\detect_key_icon.dds";
441         }
442         if (type == MWBase::World::Detect_Enchantment)
443         {
444             markerTexture = "textures\\detect_enchantment_icon.dds";
445         }
446 
447         int counter = 0;
448         for (const MWWorld::Ptr& ptr : markers)
449         {
450             const ESM::Position& worldPos = ptr.getRefData().getPosition();
451             MarkerUserData markerPos (mLocalMapRender);
452             MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
453             MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
454                                         widgetPos.top - 4,
455                                         8, 8);
456             ++counter;
457             MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
458                 widgetCoord, MyGUI::Align::Default);
459             markerWidget->setDepth(Local_MarkerAboveFogLayer);
460             markerWidget->setImageTexture(markerTexture);
461             markerWidget->setImageCoord(MyGUI::IntCoord(0,0,8,8));
462             markerWidget->setNeedMouseFocus(false);
463             mMagicMarkerWidgets.push_back(markerWidget);
464         }
465     }
466 
onFrame(float dt)467     void LocalMapBase::onFrame(float dt)
468     {
469         if (mNeedDoorMarkersUpdate)
470         {
471             updateDoorMarkers();
472             mNeedDoorMarkersUpdate = false;
473         }
474 
475         mMarkerUpdateTimer += dt;
476 
477         if (mMarkerUpdateTimer >= 0.25)
478         {
479             mMarkerUpdateTimer = 0;
480             updateMagicMarkers();
481         }
482 
483         updateRequiredMaps();
484     }
485 
widgetCropped(MyGUI::Widget * widget,MyGUI::Widget * cropTo)486     bool widgetCropped(MyGUI::Widget* widget, MyGUI::Widget* cropTo)
487     {
488         MyGUI::IntRect coord = widget->getAbsoluteRect();
489         MyGUI::IntRect croppedCoord = cropTo->getAbsoluteRect();
490         if (coord.left < croppedCoord.left && coord.right < croppedCoord.left)
491             return true;
492         if (coord.left > croppedCoord.right && coord.right > croppedCoord.right)
493             return true;
494         if (coord.top < croppedCoord.top && coord.bottom < croppedCoord.top)
495             return true;
496         if (coord.top > croppedCoord.bottom && coord.bottom > croppedCoord.bottom)
497             return true;
498         return false;
499     }
500 
updateRequiredMaps()501     void LocalMapBase::updateRequiredMaps()
502     {
503         bool needRedraw = false;
504         for (MapEntry& entry : mMaps)
505         {
506             if (widgetCropped(entry.mMapWidget, mLocalMap))
507                 continue;
508 
509             if (!entry.mMapTexture)
510             {
511                 if (!mInterior)
512                     requestMapRender(MWBase::Environment::get().getWorld()->getExterior (entry.mCellX, entry.mCellY));
513 
514                 osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(entry.mCellX, entry.mCellY);
515                 if (texture)
516                 {
517                     entry.mMapTexture.reset(new osgMyGUI::OSGTexture(texture));
518                     entry.mMapWidget->setRenderItemTexture(entry.mMapTexture.get());
519                     entry.mMapWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
520                     needRedraw = true;
521                 }
522                 else
523                     entry.mMapTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
524             }
525             if (!entry.mFogTexture && mFogOfWarToggled && mFogOfWarEnabled)
526             {
527                 osg::ref_ptr<osg::Texture2D> tex = mLocalMapRender->getFogOfWarTexture(entry.mCellX, entry.mCellY);
528                 if (tex)
529                 {
530                     entry.mFogTexture.reset(new osgMyGUI::OSGTexture(tex));
531                     entry.mFogWidget->setRenderItemTexture(entry.mFogTexture.get());
532                     entry.mFogWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
533                 }
534                 else
535                 {
536                     entry.mFogWidget->setImageTexture("black");
537                     entry.mFogTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
538                 }
539                 needRedraw = true;
540             }
541         }
542         if (needRedraw)
543             redraw();
544     }
545 
updateDoorMarkers()546     void LocalMapBase::updateDoorMarkers()
547     {
548         // clear all previous door markers
549         for (MyGUI::Widget* widget : mDoorMarkerWidgets)
550             MyGUI::Gui::getInstance().destroyWidget(widget);
551         mDoorMarkerWidgets.clear();
552 
553         MWBase::World* world = MWBase::Environment::get().getWorld();
554 
555         // Retrieve the door markers we want to show
556         std::vector<MWBase::World::DoorMarker> doors;
557         if (mInterior)
558         {
559             MWWorld::CellStore* cell = world->getInterior (mPrefix);
560             world->getDoorMarkers(cell, doors);
561         }
562         else
563         {
564             for (int dX=-mCellDistance; dX<=mCellDistance; ++dX)
565             {
566                 for (int dY=-mCellDistance; dY<=mCellDistance; ++dY)
567                 {
568                     MWWorld::CellStore* cell = world->getExterior (mCurX+dX, mCurY+dY);
569                     world->getDoorMarkers(cell, doors);
570                 }
571             }
572         }
573 
574         // Create a widget for each marker
575         int counter = 0;
576         for (MWBase::World::DoorMarker& marker : doors)
577         {
578             std::vector<std::string> destNotes;
579             CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(marker.dest);
580             for (CustomMarkerCollection::ContainerType::const_iterator iter = markers.first; iter != markers.second; ++iter)
581                 destNotes.push_back(iter->second.mNote);
582 
583             MarkerUserData data (mLocalMapRender);
584             data.notes = destNotes;
585             data.caption = marker.name;
586             MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, data);
587             MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
588                                         widgetPos.top - 4,
589                                         8, 8);
590             ++counter;
591             MarkerWidget* markerWidget = mLocalMap->createWidget<MarkerWidget>("MarkerButton",
592                 widgetCoord, MyGUI::Align::Default);
593             markerWidget->setNormalColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}")));
594             markerWidget->setHoverColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal_over}")));
595             markerWidget->setDepth(Local_MarkerLayer);
596             markerWidget->setNeedMouseFocus(true);
597             // Used by tooltips to not show the tooltip if marker is hidden by fog of war
598             markerWidget->setUserString("ToolTipType", "MapMarker");
599 
600             markerWidget->setUserData(data);
601             doorMarkerCreated(markerWidget);
602 
603             mDoorMarkerWidgets.push_back(markerWidget);
604         }
605     }
606 
updateMagicMarkers()607     void LocalMapBase::updateMagicMarkers()
608     {
609         // clear all previous markers
610         for (MyGUI::Widget* widget : mMagicMarkerWidgets)
611             MyGUI::Gui::getInstance().destroyWidget(widget);
612         mMagicMarkerWidgets.clear();
613 
614         addDetectionMarkers(MWBase::World::Detect_Creature);
615         addDetectionMarkers(MWBase::World::Detect_Key);
616         addDetectionMarkers(MWBase::World::Detect_Enchantment);
617 
618         // Add marker for the spot marked with Mark magic effect
619         MWWorld::CellStore* markedCell = nullptr;
620         ESM::Position markedPosition;
621         MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
622         if (markedCell && markedCell->isExterior() == !mInterior
623                 && (!mInterior || Misc::StringUtils::ciEqual(markedCell->getCell()->mName, mPrefix)))
624         {
625             MarkerUserData markerPos (mLocalMapRender);
626             MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
627             MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
628                                         widgetPos.top - 4,
629                                         8, 8);
630             MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
631                 widgetCoord, MyGUI::Align::Default);
632             markerWidget->setDepth(Local_MarkerAboveFogLayer);
633             markerWidget->setImageTexture("textures\\menu_map_smark.dds");
634             markerWidget->setNeedMouseFocus(false);
635             mMagicMarkerWidgets.push_back(markerWidget);
636         }
637 
638         redraw();
639     }
640 
641     // ------------------------------------------------------------------------------------------
642 
MapWindow(CustomMarkerCollection & customMarkers,DragAndDrop * drag,MWRender::LocalMap * localMapRender,SceneUtil::WorkQueue * workQueue)643     MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue)
644         : WindowPinnableBase("openmw_map_window.layout")
645         , LocalMapBase(customMarkers, localMapRender)
646         , NoDrop(drag, mMainWidget)
647         , mGlobalMap(nullptr)
648         , mGlobalMapImage(nullptr)
649         , mGlobalMapOverlay(nullptr)
650         , mGlobal(Settings::Manager::getBool("global", "Map"))
651         , mEventBoxGlobal(nullptr)
652         , mEventBoxLocal(nullptr)
653         , mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot(), workQueue))
654         , mEditNoteDialog()
655     {
656         static bool registered = false;
657         if (!registered)
658         {
659             MyGUI::FactoryManager::getInstance().registerFactory<MarkerWidget>("Widget");
660             registered = true;
661         }
662 
663         mEditNoteDialog.setVisible(false);
664         mEditNoteDialog.eventOkClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditOk);
665         mEditNoteDialog.eventDeleteClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditDelete);
666 
667         setCoord(500,0,320,300);
668 
669         getWidget(mLocalMap, "LocalMap");
670         getWidget(mGlobalMap, "GlobalMap");
671         getWidget(mGlobalMapImage, "GlobalMapImage");
672         getWidget(mGlobalMapOverlay, "GlobalMapOverlay");
673         getWidget(mPlayerArrowLocal, "CompassLocal");
674         getWidget(mPlayerArrowGlobal, "CompassGlobal");
675 
676         mPlayerArrowGlobal->setDepth(Global_CompassLayer);
677         mPlayerArrowGlobal->setNeedMouseFocus(false);
678         mGlobalMapImage->setDepth(Global_MapLayer);
679         mGlobalMapOverlay->setDepth(Global_ExploreOverlayLayer);
680 
681         mLastScrollWindowCoordinates = mLocalMap->getCoord();
682         mLocalMap->eventChangeCoord += MyGUI::newDelegate(this, &MapWindow::onChangeScrollWindowCoord);
683 
684         mGlobalMap->setVisible (false);
685 
686         getWidget(mButton, "WorldButton");
687         mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
688         mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : "#{sWorld}");
689 
690         getWidget(mEventBoxGlobal, "EventBoxGlobal");
691         mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
692         mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
693         mEventBoxGlobal->setDepth(Global_ExploreOverlayLayer);
694 
695         getWidget(mEventBoxLocal, "EventBoxLocal");
696         mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
697         mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
698         mEventBoxLocal->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onMapDoubleClicked);
699 
700         LocalMapBase::init(mLocalMap, mPlayerArrowLocal);
701 
702         mGlobalMap->setVisible(mGlobal);
703         mLocalMap->setVisible(!mGlobal);
704     }
705 
onNoteEditOk()706     void MapWindow::onNoteEditOk()
707     {
708         if (mEditNoteDialog.getDeleteButtonShown())
709             mCustomMarkers.updateMarker(mEditingMarker, mEditNoteDialog.getText());
710         else
711         {
712             mEditingMarker.mNote = mEditNoteDialog.getText();
713             mCustomMarkers.addMarker(mEditingMarker);
714         }
715 
716         mEditNoteDialog.setVisible(false);
717     }
718 
onNoteEditDelete()719     void MapWindow::onNoteEditDelete()
720     {
721         ConfirmationDialog* confirmation = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
722         confirmation->askForConfirmation("#{sDeleteNote}");
723         confirmation->eventCancelClicked.clear();
724         confirmation->eventOkClicked.clear();
725         confirmation->eventOkClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditDeleteConfirm);
726     }
727 
onNoteEditDeleteConfirm()728     void MapWindow::onNoteEditDeleteConfirm()
729     {
730         mCustomMarkers.deleteMarker(mEditingMarker);
731 
732         mEditNoteDialog.setVisible(false);
733     }
734 
onCustomMarkerDoubleClicked(MyGUI::Widget * sender)735     void MapWindow::onCustomMarkerDoubleClicked(MyGUI::Widget *sender)
736     {
737         mEditingMarker = *sender->getUserData<ESM::CustomMarker>();
738         mEditNoteDialog.setText(mEditingMarker.mNote);
739         mEditNoteDialog.showDeleteButton(true);
740         mEditNoteDialog.setVisible(true);
741     }
742 
onMapDoubleClicked(MyGUI::Widget * sender)743     void MapWindow::onMapDoubleClicked(MyGUI::Widget *sender)
744     {
745         MyGUI::IntPoint clickedPos = MyGUI::InputManager::getInstance().getMousePosition();
746 
747         MyGUI::IntPoint widgetPos = clickedPos - mEventBoxLocal->getAbsolutePosition();
748         int x = int(widgetPos.left/float(mMapWidgetSize))-mCellDistance;
749         int y = (int(widgetPos.top/float(mMapWidgetSize))-mCellDistance)*-1;
750         float nX = widgetPos.left/float(mMapWidgetSize) - int(widgetPos.left/float(mMapWidgetSize));
751         float nY = widgetPos.top/float(mMapWidgetSize) - int(widgetPos.top/float(mMapWidgetSize));
752         x += mCurX;
753         y += mCurY;
754 
755         osg::Vec2f worldPos;
756         if (mInterior)
757         {
758             worldPos = mLocalMapRender->interiorMapToWorldPosition(nX, nY, x, y);
759         }
760         else
761         {
762             worldPos.x() = (x + nX) * cellSize;
763             worldPos.y() = (y + (1.0f-nY)) * cellSize;
764         }
765 
766         mEditingMarker.mWorldX = worldPos.x();
767         mEditingMarker.mWorldY = worldPos.y();
768 
769         mEditingMarker.mCell.mPaged = !mInterior;
770         if (mInterior)
771             mEditingMarker.mCell.mWorldspace = LocalMapBase::mPrefix;
772         else
773         {
774             mEditingMarker.mCell.mWorldspace = ESM::CellId::sDefaultWorldspace;
775             mEditingMarker.mCell.mIndex.mX = x;
776             mEditingMarker.mCell.mIndex.mY = y;
777         }
778 
779         mEditNoteDialog.setVisible(true);
780         mEditNoteDialog.showDeleteButton(false);
781         mEditNoteDialog.setText("");
782     }
783 
onChangeScrollWindowCoord(MyGUI::Widget * sender)784     void MapWindow::onChangeScrollWindowCoord(MyGUI::Widget* sender)
785     {
786         MyGUI::IntCoord currentCoordinates = sender->getCoord();
787 
788         MyGUI::IntPoint currentViewPortCenter = MyGUI::IntPoint(currentCoordinates.width / 2, currentCoordinates.height / 2);
789         MyGUI::IntPoint lastViewPortCenter = MyGUI::IntPoint(mLastScrollWindowCoordinates.width / 2, mLastScrollWindowCoordinates.height / 2);
790         MyGUI::IntPoint viewPortCenterDiff = currentViewPortCenter - lastViewPortCenter;
791 
792         mLocalMap->setViewOffset(mLocalMap->getViewOffset() + viewPortCenterDiff);
793         mGlobalMap->setViewOffset(mGlobalMap->getViewOffset() + viewPortCenterDiff);
794 
795         mLastScrollWindowCoordinates = currentCoordinates;
796     }
797 
setVisible(bool visible)798     void MapWindow::setVisible(bool visible)
799     {
800         WindowBase::setVisible(visible);
801         mButton->setVisible(visible && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_None);
802     }
803 
renderGlobalMap()804     void MapWindow::renderGlobalMap()
805     {
806         mGlobalMapRender->render();
807         mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
808         mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
809     }
810 
~MapWindow()811     MapWindow::~MapWindow()
812     {
813         delete mGlobalMapRender;
814     }
815 
setCellName(const std::string & cellName)816     void MapWindow::setCellName(const std::string& cellName)
817     {
818         setTitle("#{sCell=" + cellName + "}");
819     }
820 
addVisitedLocation(const std::string & name,int x,int y)821     void MapWindow::addVisitedLocation(const std::string& name, int x, int y)
822     {
823         CellId cell;
824         cell.first = x;
825         cell.second = y;
826         if (mMarkers.insert(cell).second)
827         {
828             float worldX, worldY;
829             mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY);
830 
831             int markerSize = 12;
832             int offset = mGlobalMapRender->getCellSize()/2 - markerSize/2;
833             MyGUI::IntCoord widgetCoord(
834                         static_cast<int>(worldX * mGlobalMapRender->getWidth()+offset),
835                         static_cast<int>(worldY * mGlobalMapRender->getHeight() + offset),
836                         markerSize, markerSize);
837 
838             MyGUI::Widget* markerWidget = mGlobalMap->createWidget<MyGUI::Widget>("MarkerButton",
839                 widgetCoord, MyGUI::Align::Default);
840 
841             markerWidget->setUserString("Caption_TextOneLine", "#{sCell=" + name + "}");
842 
843             setGlobalMapMarkerTooltip(markerWidget, x, y);
844 
845             markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
846 
847             markerWidget->setNeedMouseFocus(true);
848             markerWidget->setColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}")));
849             markerWidget->setDepth(Global_MarkerLayer);
850             markerWidget->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
851             markerWidget->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
852             mGlobalMapMarkers[std::make_pair(x,y)] = markerWidget;
853         }
854     }
855 
cellExplored(int x,int y)856     void MapWindow::cellExplored(int x, int y)
857     {
858         mGlobalMapRender->cleanupCameras();
859         mGlobalMapRender->exploreCell(x, y, mLocalMapRender->getMapTexture(x, y));
860     }
861 
onFrame(float dt)862     void MapWindow::onFrame(float dt)
863     {
864         LocalMapBase::onFrame(dt);
865         NoDrop::onFrame(dt);
866     }
867 
setGlobalMapMarkerTooltip(MyGUI::Widget * markerWidget,int x,int y)868     void MapWindow::setGlobalMapMarkerTooltip(MyGUI::Widget* markerWidget, int x, int y)
869     {
870         ESM::CellId cellId;
871         cellId.mIndex.mX = x;
872         cellId.mIndex.mY = y;
873         cellId.mWorldspace = ESM::CellId::sDefaultWorldspace;
874         cellId.mPaged = true;
875         CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(cellId);
876         std::vector<std::string> destNotes;
877         for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second; ++it)
878             destNotes.push_back(it->second.mNote);
879 
880         if (!destNotes.empty())
881         {
882             MarkerUserData data (nullptr);
883             data.notes = destNotes;
884             data.caption = markerWidget->getUserString("Caption_TextOneLine");
885             markerWidget->setUserData(data);
886             markerWidget->setUserString("ToolTipType", "MapMarker");
887         }
888         else
889         {
890             markerWidget->setUserString("ToolTipType", "Layout");
891         }
892     }
893 
updateCustomMarkers()894     void MapWindow::updateCustomMarkers()
895     {
896         LocalMapBase::updateCustomMarkers();
897 
898         for (auto& widgetPair : mGlobalMapMarkers)
899         {
900             int x = widgetPair.first.first;
901             int y = widgetPair.first.second;
902             MyGUI::Widget* markerWidget = widgetPair.second;
903             setGlobalMapMarkerTooltip(markerWidget, x, y);
904         }
905     }
906 
onDragStart(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)907     void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
908     {
909         if (_id!=MyGUI::MouseButton::Left) return;
910         mLastDragPos = MyGUI::IntPoint(_left, _top);
911     }
912 
onMouseDrag(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)913     void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
914     {
915         if (_id!=MyGUI::MouseButton::Left) return;
916 
917         MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
918 
919         if (!mGlobal)
920             mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff );
921         else
922             mGlobalMap->setViewOffset( mGlobalMap->getViewOffset() + diff );
923 
924         mLastDragPos = MyGUI::IntPoint(_left, _top);
925     }
926 
onWorldButtonClicked(MyGUI::Widget * _sender)927     void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
928     {
929         mGlobal = !mGlobal;
930         mGlobalMap->setVisible(mGlobal);
931         mLocalMap->setVisible(!mGlobal);
932 
933         Settings::Manager::setBool("global", "Map", mGlobal);
934 
935         mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" :
936                 "#{sWorld}");
937 
938         if (mGlobal)
939             globalMapUpdatePlayer ();
940     }
941 
onPinToggled()942     void MapWindow::onPinToggled()
943     {
944         Settings::Manager::setBool("map pin", "Windows", mPinned);
945 
946         MWBase::Environment::get().getWindowManager()->setMinimapVisibility(!mPinned);
947     }
948 
onTitleDoubleClicked()949     void MapWindow::onTitleDoubleClicked()
950     {
951         if (MyGUI::InputManager::getInstance().isShiftPressed())
952             MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
953         else if (!mPinned)
954             MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map);
955     }
956 
onOpen()957     void MapWindow::onOpen()
958     {
959         ensureGlobalMapLoaded();
960 
961         globalMapUpdatePlayer();
962     }
963 
globalMapUpdatePlayer()964     void MapWindow::globalMapUpdatePlayer ()
965     {
966         // For interiors, position is set by WindowManager via setGlobalMapPlayerPosition
967         if (MWBase::Environment::get().getWorld ()->isCellExterior ())
968         {
969             osg::Vec3f pos = MWBase::Environment::get().getWorld ()->getPlayerPtr().getRefData().getPosition().asVec3();
970             setGlobalMapPlayerPosition(pos.x(), pos.y());
971         }
972     }
973 
notifyPlayerUpdate()974     void MapWindow::notifyPlayerUpdate ()
975     {
976         globalMapUpdatePlayer ();
977 
978         setGlobalMapPlayerDir(mLastDirectionX, mLastDirectionY);
979     }
980 
setGlobalMapPlayerPosition(float worldX,float worldY)981     void MapWindow::setGlobalMapPlayerPosition(float worldX, float worldY)
982     {
983         float x, y;
984         mGlobalMapRender->worldPosToImageSpace (worldX, worldY, x, y);
985         x *= mGlobalMapRender->getWidth();
986         y *= mGlobalMapRender->getHeight();
987 
988         mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(static_cast<int>(x - 16), static_cast<int>(y - 16)));
989 
990         // set the view offset so that player is in the center
991         MyGUI::IntSize viewsize = mGlobalMap->getSize();
992         MyGUI::IntPoint viewoffs(static_cast<int>(viewsize.width * 0.5f - x), static_cast<int>(viewsize.height *0.5 - y));
993         mGlobalMap->setViewOffset(viewoffs);
994     }
995 
setGlobalMapPlayerDir(const float x,const float y)996     void MapWindow::setGlobalMapPlayerDir(const float x, const float y)
997     {
998         MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
999         MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
1000         rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
1001         float angle = std::atan2(x,y);
1002         rotatingSubskin->setAngle(angle);
1003     }
1004 
ensureGlobalMapLoaded()1005     void MapWindow::ensureGlobalMapLoaded()
1006     {
1007         if (!mGlobalMapTexture.get())
1008         {
1009             mGlobalMapTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getBaseTexture()));
1010             mGlobalMapImage->setRenderItemTexture(mGlobalMapTexture.get());
1011             mGlobalMapImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
1012 
1013             mGlobalMapOverlayTexture.reset(new osgMyGUI::OSGTexture(mGlobalMapRender->getOverlayTexture()));
1014             mGlobalMapOverlay->setRenderItemTexture(mGlobalMapOverlayTexture.get());
1015             mGlobalMapOverlay->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
1016 
1017             // Redraw children in proper order
1018             mGlobalMap->getParent()->_updateChilds();
1019         }
1020     }
1021 
clear()1022     void MapWindow::clear()
1023     {
1024         mMarkers.clear();
1025 
1026         mGlobalMapRender->clear();
1027         mChanged = true;
1028 
1029         for (auto& widgetPair : mGlobalMapMarkers)
1030             MyGUI::Gui::getInstance().destroyWidget(widgetPair.second);
1031         mGlobalMapMarkers.clear();
1032     }
1033 
write(ESM::ESMWriter & writer,Loading::Listener & progress)1034     void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress)
1035     {
1036         ESM::GlobalMap map;
1037         mGlobalMapRender->write(map);
1038 
1039         map.mMarkers = mMarkers;
1040 
1041         writer.startRecord(ESM::REC_GMAP);
1042         map.save(writer);
1043         writer.endRecord(ESM::REC_GMAP);
1044     }
1045 
readRecord(ESM::ESMReader & reader,uint32_t type)1046     void MapWindow::readRecord(ESM::ESMReader &reader, uint32_t type)
1047     {
1048         if (type == ESM::REC_GMAP)
1049         {
1050             ESM::GlobalMap map;
1051             map.load(reader);
1052 
1053             mGlobalMapRender->read(map);
1054 
1055             for (const ESM::GlobalMap::CellId& cellId : map.mMarkers)
1056             {
1057                 const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(cellId.first, cellId.second);
1058                 if (cell && !cell->mName.empty())
1059                     addVisitedLocation(cell->mName, cellId.first, cellId.second);
1060             }
1061         }
1062     }
1063 
setAlpha(float alpha)1064     void MapWindow::setAlpha(float alpha)
1065     {
1066         NoDrop::setAlpha(alpha);
1067         // can't allow showing map with partial transparency, as the fog of war will also go transparent
1068         // and reveal parts of the map you shouldn't be able to see
1069         for (MapEntry& entry : mMaps)
1070             entry.mMapWidget->setVisible(alpha == 1);
1071     }
1072 
customMarkerCreated(MyGUI::Widget * marker)1073     void MapWindow::customMarkerCreated(MyGUI::Widget *marker)
1074     {
1075         marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
1076         marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
1077         marker->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onCustomMarkerDoubleClicked);
1078     }
1079 
doorMarkerCreated(MyGUI::Widget * marker)1080     void MapWindow::doorMarkerCreated(MyGUI::Widget *marker)
1081     {
1082         marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
1083         marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
1084     }
1085 
1086     // -------------------------------------------------------------------
1087 
EditNoteDialog()1088     EditNoteDialog::EditNoteDialog()
1089         : WindowModal("openmw_edit_note.layout")
1090     {
1091         getWidget(mOkButton, "OkButton");
1092         getWidget(mCancelButton, "CancelButton");
1093         getWidget(mDeleteButton, "DeleteButton");
1094         getWidget(mTextEdit, "TextEdit");
1095 
1096         mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNoteDialog::onCancelButtonClicked);
1097         mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNoteDialog::onOkButtonClicked);
1098         mDeleteButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNoteDialog::onDeleteButtonClicked);
1099     }
1100 
showDeleteButton(bool show)1101     void EditNoteDialog::showDeleteButton(bool show)
1102     {
1103         mDeleteButton->setVisible(show);
1104     }
1105 
getDeleteButtonShown()1106     bool EditNoteDialog::getDeleteButtonShown()
1107     {
1108         return mDeleteButton->getVisible();
1109     }
1110 
setText(const std::string & text)1111     void EditNoteDialog::setText(const std::string &text)
1112     {
1113         mTextEdit->setCaption(MyGUI::TextIterator::toTagsString(text));
1114     }
1115 
getText()1116     std::string EditNoteDialog::getText()
1117     {
1118         return MyGUI::TextIterator::getOnlyText(mTextEdit->getCaption());
1119     }
1120 
onOpen()1121     void EditNoteDialog::onOpen()
1122     {
1123         WindowModal::onOpen();
1124         center();
1125         MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit);
1126     }
1127 
onCancelButtonClicked(MyGUI::Widget * sender)1128     void EditNoteDialog::onCancelButtonClicked(MyGUI::Widget *sender)
1129     {
1130         setVisible(false);
1131     }
1132 
onOkButtonClicked(MyGUI::Widget * sender)1133     void EditNoteDialog::onOkButtonClicked(MyGUI::Widget *sender)
1134     {
1135         eventOkClicked();
1136     }
1137 
onDeleteButtonClicked(MyGUI::Widget * sender)1138     void EditNoteDialog::onDeleteButtonClicked(MyGUI::Widget *sender)
1139     {
1140         eventDeleteClicked();
1141     }
1142 
isPositionExplored() const1143     bool LocalMapBase::MarkerUserData::isPositionExplored() const
1144     {
1145         if (!mLocalMapRender)
1146             return true;
1147         return mLocalMapRender->isPositionExplored(nX, nY, cellX, cellY);
1148     }
1149 
1150 }
1151