ManaPlus
minimap.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "gui/windows/minimap.h"
25 
26 #include "actormanager.h"
27 #include "configuration.h"
28 #include "party.h"
29 #include "settings.h"
30 
31 #include "being/localplayer.h"
32 
34 
35 #include "fs/virtfs/fs.h"
36 
37 #include "gui/popupmanager.h"
38 #include "gui/viewport.h"
39 #include "gui/userpalette.h"
40 
41 #include "gui/popups/popupmenu.h"
42 #include "gui/popups/textpopup.h"
43 
45 
46 #include "resources/imagehelper.h"
47 
48 #include "resources/image/image.h"
49 
50 #include "resources/map/map.h"
51 #include "resources/map/metatile.h"
52 
54 
55 #include "utils/gettext.h"
56 #include "utils/foreach.h"
57 #include "utils/sdlcheckutils.h"
58 #include "utils/stdmove.h"
59 
60 #include "debug.h"
61 
62 Minimap *minimap = nullptr;
63 bool Minimap::mShow = true;
64 
66  // TRANSLATORS: mini map window name
67  Window(_("Map"), Modal_false, nullptr, "map.xml"),
68  mWidthProportion(0.5),
69  mHeightProportion(0.5),
70  mMapImage(nullptr),
71  mMapOriginX(0),
72  mMapOriginY(0),
73  mCustomMapImage(false),
74  mAutoResize(config.getBoolValue("autoresizeminimaps"))
75 {
76  setWindowName("Minimap");
77  mShow = config.getValueBool(getWindowName() + "Show", true);
78 
79  config.addListener("autoresizeminimaps", this);
80 
81  setDefaultSize(5, 25, 100, 100);
82  // set this to false as the minimap window size is changed
83  // depending on the map size
84  setResizable(true);
85  if (setupWindow != nullptr)
87 
88  setDefaultVisible(true);
89  setSaveVisible(true);
90 
91  setStickyButton(true);
92  setSticky(false);
93 
96  enableVisibleSound(true);
97 }
98 
100 {
101  config.setValue(getWindowName() + "Show", mShow);
102  config.removeListeners(this);
104  deleteMapImage();
105 }
106 
108 {
109  if (mMapImage != nullptr)
110  {
111  if (mCustomMapImage)
112  delete mMapImage;
113  else
114  mMapImage->decRef();
115  mMapImage = nullptr;
116  }
117 }
118 
119 void Minimap::setMap(const Map *const map)
120 {
121  BLOCK_START("Minimap::setMap")
122  std::string caption;
123 
124  if (map != nullptr)
125  caption = map->getName();
126 
127  if (caption.empty())
128  {
129  // TRANSLATORS: mini map window name
130  caption = _("Map");
131  }
132 
133  setCaption(caption);
134  deleteMapImage();
135 
136  if (map != nullptr)
137  {
138  if (config.getBoolValue("showExtMinimaps"))
139  {
140  SDL_Surface *const surface = MSDL_CreateRGBSurface(SDL_SWSURFACE,
141  map->getWidth(), map->getHeight(), 32,
142  0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
143  if (surface == nullptr)
144  {
145  if (!isSticky())
147  BLOCK_END("Minimap::setMap")
148  return;
149  }
150 
151  // I'm not sure if the locks are necessary since it's a SWSURFACE
152  SDL_LockSurface(surface);
153  int* data = static_cast<int*>(surface->pixels);
154  if (data == nullptr)
155  {
156  if (!isSticky())
158  BLOCK_END("Minimap::setMap")
159  return;
160  }
161  const int size = surface->h * surface->w;
162  const int mask = (BlockMask::WALL |
166 
167  for (int ptr = 0; ptr < size; ptr ++)
168  {
169  *(data ++) = (map->mMetaTiles[ptr].blockmask & mask) != 0 ?
170  0x0 : 0x00ffffff;
171  }
172 
173  SDL_UnlockSurface(surface);
174 
175  mMapImage = imageHelper->loadSurface(surface);
176  mMapImage->setAlpha(settings.guiAlpha);
177  mCustomMapImage = true;
178  MSDL_FreeSurface(surface);
179  }
180  else
181  {
182  std::string tempname = pathJoin(paths.getStringValue("minimaps"),
183  map->getFilename()).append(".png");
184 
185  std::string minimapName = map->getProperty("minimap",
186  std::string());
187 
188  if (minimapName.empty() && VirtFs::exists(tempname))
189  minimapName = tempname;
190 
191  if (minimapName.empty())
192  {
193  tempname = pathJoin("graphics/minimaps",
194  map->getFilename()).append(".png");
195  if (VirtFs::exists(tempname))
196  minimapName = STD_MOVE(tempname);
197  }
198 
199  if (!minimapName.empty())
200  mMapImage = Loader::getImage(minimapName);
201  else
202  mMapImage = nullptr;
203  mCustomMapImage = false;
204  }
205  }
206 
207  if ((mMapImage != nullptr) && (map != nullptr))
208  {
209  const int width = mMapImage->mBounds.w + 2 * getPadding();
210  const int height = mMapImage->mBounds.h
212  const int mapWidth = mMapImage->mBounds.w < 100 ? width : 100;
213  const int mapHeight = mMapImage->mBounds.h < 100 ? height : 100;
214  const int minWidth = mapWidth > 310 ? 310 : mapWidth;
215  const int minHeight = mapHeight > 220 ? 220 : mapHeight;
216 
217  setMinWidth(minWidth);
218  setMinHeight(minHeight);
219 
220  mWidthProportion = static_cast<float>(
221  mMapImage->mBounds.w) / static_cast<float>(map->getWidth());
222  mHeightProportion = static_cast<float>(
223  mMapImage->mBounds.h) / static_cast<float>(map->getHeight());
224 
225  setMaxWidth(width);
226  setMaxHeight(height);
227  if (mAutoResize)
228  {
229  setWidth(width);
230  setHeight(height);
231  }
232 
233  const Rect &rect = mDimension;
234  setDefaultSize(rect.x, rect.y, rect.width, rect.height);
236 
237  if (mShow)
239  }
240  else
241  {
242  if (!isSticky())
244  }
245  BLOCK_END("Minimap::setMap")
246 }
247 
249 {
252 }
253 
254 void Minimap::draw(Graphics *const graphics)
255 {
256  BLOCK_START("Minimap::draw")
257 
258  Window::draw(graphics);
259  draw2(graphics);
260 }
261 
262 void Minimap::safeDraw(Graphics *const graphics)
263 {
264  BLOCK_START("Minimap::draw")
265 
266  Window::safeDraw(graphics);
267  draw2(graphics);
268 }
269 
270 void Minimap::draw2(Graphics *const graphics)
271 {
272  if (userPalette == nullptr ||
273  localPlayer == nullptr ||
274  viewport == nullptr)
275  {
276  BLOCK_END("Minimap::draw")
277  return;
278  }
279 
280  const Rect a = getChildrenArea();
281 
282  graphics->pushClipArea(a);
283 
284  if (actorManager == nullptr)
285  {
286  BLOCK_END("Minimap::draw")
287  return;
288  }
289 
290  mMapOriginX = 0;
291  mMapOriginY = 0;
292 
293  if (mMapImage != nullptr)
294  {
295  const SDL_Rect &rect = mMapImage->mBounds;
296  const int w = rect.w;
297  const int h = rect.h;
298  if (w > a.width || h > a.height)
299  {
300  mMapOriginX = (a.width / 2) - (localPlayer->mPixelX +
302 
303  mMapOriginY = (a.height / 2) - (localPlayer->mPixelY +
305 
306  const int minOriginX = a.width - w;
307  const int minOriginY = a.height - h;
308 
309  if (mMapOriginX < minOriginX)
310  mMapOriginX = minOriginX;
311  if (mMapOriginY < minOriginY)
312  mMapOriginY = minOriginY;
313  if (mMapOriginX > 0)
314  mMapOriginX = 0;
315  if (mMapOriginY > 0)
316  mMapOriginY = 0;
317  }
318 
320  }
321 
322  const ActorSprites &actors = actorManager->getAll();
323  FOR_EACH (ActorSpritesConstIterator, it, actors)
324  {
325  if (((*it) == nullptr) || (*it)->getType() == ActorType::FloorItem)
326  continue;
327 
328  const Being *const being = static_cast<const Being *>(*it);
329  if (being == nullptr)
330  continue;
331 
332  int dotSize = 2;
334 
335  if (being == localPlayer)
336  {
337  type = UserColorId::SELF;
338  dotSize = 3;
339  }
340  else if (being->isGM())
341  {
342  type = UserColorId::GM;
343  }
344  else if (being->getGuild() == localPlayer->getGuild()
345  || being->getGuildName() == localPlayer->getGuildName())
346  {
347  type = UserColorId::GUILD;
348  }
349  else
350  {
351  switch (being->getType())
352  {
353  case ActorType::Monster:
354  type = UserColorId::MONSTER;
355  break;
356 
357  case ActorType::Npc:
358  type = UserColorId::NPC;
359  break;
360 
361  case ActorType::Portal:
363  break;
364 
365  case ActorType::Pet:
366  type = UserColorId::PET;
367  break;
369  type = UserColorId::MERCENARY;
370  break;
371 
374  break;
375 
377  type = UserColorId::SKILLUNIT;
378  break;
379  case ActorType::Avatar:
380  case ActorType::Unknown:
381  case ActorType::Player:
384  default:
385  continue;
386  }
387  }
388 
389  if (userPalette != nullptr)
390  graphics->setColor(userPalette->getColor(type, 255U));
391 
392  const int offsetHeight = CAST_S32(static_cast<float>(
393  dotSize - 1) * mHeightProportion);
394  const int offsetWidth = CAST_S32(static_cast<float>(
395  dotSize - 1) * mWidthProportion);
396  graphics->fillRectangle(Rect(
397  (being->mPixelX * mWidthProportion) / 32
398  + mMapOriginX - offsetWidth,
399  (being->mPixelY * mHeightProportion) / 32
400  + mMapOriginY - offsetHeight, dotSize, dotSize));
401  }
402 
403  if (localPlayer->isInParty())
404  {
405  const Party *const party = localPlayer->getParty();
406  if (party != nullptr)
407  {
408  const PartyMember *const m = party->getMember(
409  localPlayer->getName());
410  const Party::MemberList *const members = party->getMembers();
411  if (m != nullptr)
412  {
413  const std::string curMap = m->getMap();
414  Party::MemberList::const_iterator it = members->begin();
415  const Party::MemberList::const_iterator
416  it_end = members->end();
417  while (it != it_end)
418  {
419  const PartyMember *const member = *it;
420  if ((member != nullptr) && member->getMap() == curMap
421  && member->getOnline() && member != m)
422  {
423  if (userPalette != nullptr)
424  {
425  graphics->setColor(userPalette->getColor(
426  UserColorId::PARTY, 255U));
427  }
428 
429  const int offsetHeight = CAST_S32(
431  const int offsetWidth = CAST_S32(
433 
434  graphics->fillRectangle(Rect(
435  CAST_S32(member->getX()
436  * mWidthProportion) + mMapOriginX - offsetWidth,
437  CAST_S32(member->getY()
438  * mHeightProportion) + mMapOriginY - offsetHeight,
439  2, 2));
440  }
441  ++ it;
442  }
443  }
444  }
445  }
446 
447  const int gw = graphics->getWidth();
448  const int gh = graphics->getHeight();
449  int x = (localPlayer->mPixelX - (gw / 2)
451  * mWidthProportion / 32 + mMapOriginX;
452  int y = (localPlayer->mPixelY - (gh / 2)
455 
456  const int w = CAST_S32(static_cast<float>(
457  gw) * mWidthProportion / 32);
458  const int h = CAST_S32(static_cast<float>(
459  gh) * mHeightProportion / 32);
460 
461  if (w <= a.width)
462  {
463  if (x < 0 && (w != 0))
464  x = 0;
465  if (x + w > a.width)
466  x = a.width - w;
467  }
468  if (h <= a.height)
469  {
470  if (y < 0 && (h != 0))
471  y = 0;
472  if (y + h > a.height)
473  y = a.height - h;
474  }
475 
476  graphics->setColor(userPalette->getColor(UserColorId::PC, 255U));
477  graphics->drawRectangle(Rect(x, y, w, h));
478  graphics->popClipArea();
479  BLOCK_END("Minimap::draw")
480 }
481 
483 {
484  if (event.getButton() == MouseButton::RIGHT)
485  return;
486  Window::mousePressed(event);
487 }
488 
490 {
491  Window::mouseReleased(event);
492 
493  if ((localPlayer == nullptr) || (popupManager == nullptr))
494  return;
495 
496  if (event.getButton() == MouseButton::LEFT)
497  {
498  int x = event.getX();
499  int y = event.getY();
500  screenToMap(x, y);
501 
503  }
504  else if (event.getButton() == MouseButton::RIGHT)
505  {
506  int x = event.getX();
507  int y = event.getY();
508  screenToMap(x, y);
510  viewport->mMouseY,
511  x, y,
512  true);
513  }
514 }
515 
517 {
518  Window::mouseMoved(event);
519  const int x = event.getX();
520  const int y = event.getY();
521  const Rect &rect = mDimension;
522  textPopup->show(x + rect.x, y + rect.y, mCaption);
523 }
524 
526 {
527  Window::mouseExited(event);
528  textPopup->hide();
529 }
530 
531 void Minimap::screenToMap(int &x, int &y)
532 {
533  const Rect a = getChildrenArea();
536 }
537 
538 void Minimap::optionChanged(const std::string &name)
539 {
540  if (name == "autoresizeminimaps")
541  mAutoResize = config.getBoolValue("autoresizeminimaps");
542 }
ActorManager * actorManager
std::set< ActorSprite * > ActorSprites
Definition: actormanager.h:57
ActorSprites::const_iterator ActorSpritesConstIterator
Definition: actormanager.h:61
#define fromBool(val, name)
Definition: booldefines.h:49
#define CAST_S32
Definition: cast.h:30
const ActorSprites & getAll() const A_CONST
int mPixelX
Definition: actor.h:133
int mPixelY
Definition: actor.h:134
std::string getMap() const
Definition: avatar.h:120
bool getOnline() const
Definition: avatar.h:81
int getY() const
Definition: avatar.h:132
int getX() const
Definition: avatar.h:126
Definition: being.h:96
Party * getParty() const
Definition: being.h:330
const Guild * getGuild(const std::string &guildName) const
Definition: being.cpp:1258
bool isGM() const
Definition: being.h:659
const std::string & getName() const
Definition: being.h:232
const std::string & getGuildName() const
Definition: being.h:259
bool isInParty() const
Definition: being.h:321
ActorTypeT getType() const
Definition: being.h:116
bool getValueBool(const std::string &key, const bool deflt) const
bool getBoolValue(const std::string &key) const
std::string getStringValue(const std::string &key) const
void addListener(const std::string &key, ConfigListener *const listener)
void setValue(const std::string &key, const std::string &value)
void removeListeners(ConfigListener *const listener)
virtual void drawImage(const Image *const image, int dstX, int dstY)=0
virtual void popClipArea()
Definition: graphics.cpp:739
virtual void fillRectangle(const Rect &rectangle)=0
int getHeight() const
Definition: graphics.cpp:648
virtual void setColor(const Color &color)
Definition: graphics.h:320
virtual void drawRectangle(const Rect &rectangle)=0
virtual void pushClipArea(const Rect &area)
Definition: graphics.cpp:677
int getWidth() const
Definition: graphics.cpp:643
virtual Image * loadSurface(SDL_Surface *const)
Definition: imagehelper.h:73
bool navigateTo(const int x, const int y)
Definition: map.h:75
const std::string getFilename() const
Definition: map.cpp:848
int getHeight() const
Definition: map.h:172
MetaTile *const mMetaTiles
Definition: map.h:417
const std::string getName() const
Definition: map.cpp:840
int getWidth() const
Definition: map.h:166
int mMapOriginY
Definition: minimap.h:88
void setMap(const Map *const map)
Definition: minimap.cpp:119
void optionChanged(const std::string &name)
Definition: minimap.cpp:538
void mouseReleased(MouseEvent &event)
Definition: minimap.cpp:489
void mousePressed(MouseEvent &event)
Definition: minimap.cpp:482
static bool mShow
Definition: minimap.h:91
void toggle()
Definition: minimap.cpp:248
~Minimap()
Definition: minimap.cpp:99
int mMapOriginX
Definition: minimap.h:87
void mouseMoved(MouseEvent &event)
Definition: minimap.cpp:516
Minimap()
Definition: minimap.cpp:65
Image * mMapImage
Definition: minimap.h:86
void screenToMap(int &x, int &y)
Definition: minimap.cpp:531
void draw2(Graphics *const graphics)
Definition: minimap.cpp:270
bool mCustomMapImage
Definition: minimap.h:89
void safeDraw(Graphics *const graphics)
Definition: minimap.cpp:262
void deleteMapImage()
Definition: minimap.cpp:107
float mHeightProportion
Definition: minimap.h:85
void mouseExited(MouseEvent &event)
Definition: minimap.cpp:525
bool mAutoResize
Definition: minimap.h:90
void draw(Graphics *const graphics)
Definition: minimap.cpp:254
float mWidthProportion
Definition: minimap.h:84
MouseButtonT getButton() const
Definition: mouseevent.h:116
Definition: party.h:63
std::vector< PartyMember * > MemberList
Definition: party.h:157
void showMapPopup(const int x, const int y, const int x2, const int y2, const bool isMinimap)
Definition: popupmenu.cpp:805
void hide()
Definition: popup.cpp:265
const std::string getProperty(const std::string &name, const std::string &def) const
Definition: properties.h:59
Definition: rect.h:74
int y
Definition: rect.h:214
int width
Definition: rect.h:219
int x
Definition: rect.h:209
int height
Definition: rect.h:224
float guiAlpha
Definition: settings.h:131
void registerWindowForReset(Window *const window)
void show(const int x, const int y, const std::string &str1)
Definition: textpopup.h:57
const Color & getColor(UserColorIdT type, const unsigned int alpha)
Definition: userpalette.h:160
int mMouseX
Definition: viewport.h:154
int getCameraRelativeY() const
Definition: viewport.h:143
int getCameraRelativeX() const
Definition: viewport.h:140
int mMouseY
Definition: viewport.h:155
void setWidth(const int width)
Definition: widget.cpp:133
Rect mDimension
Definition: widget.h:1101
void setHeight(const int height)
Definition: widget.cpp:140
Definition: window.h:102
void safeDraw(Graphics *const graphics)
Definition: window.cpp:423
void mouseReleased(MouseEvent &event)
Definition: window.cpp:907
void setSaveVisible(const bool save)
Definition: window.h:300
void setResizable(const bool resize)
Definition: window.cpp:627
void setMaxWidth(const int width)
Definition: window.cpp:617
virtual void setVisible(Visible visible)
Definition: window.cpp:778
bool isWindowVisible() const
Definition: window.h:484
void setWindowName(const std::string &name)
Definition: window.h:355
unsigned int getTitleBarHeight() const
Definition: window.h:522
void mouseExited(MouseEvent &event)
Definition: window.cpp:924
bool isSticky() const
Definition: window.h:253
virtual void resetToDefaultSize()
Definition: window.cpp:1259
void setSticky(const bool sticky)
Definition: window.cpp:766
void setCaption(const std::string &caption)
Definition: window.h:531
void setMinHeight(const int height)
Definition: window.cpp:604
void mouseMoved(MouseEvent &event)
Definition: window.cpp:967
void setMaxHeight(const int height)
Definition: window.cpp:622
void setMinWidth(const int width)
Definition: window.cpp:591
void mousePressed(MouseEvent &event)
Definition: window.cpp:836
int getPadding() const
Definition: window.h:504
void enableVisibleSound(bool b)
Definition: window.h:481
void draw(Graphics *const graphics)
Definition: window.cpp:311
const std::string & getWindowName() const
Definition: window.h:361
Rect getChildrenArea()
Definition: window.cpp:1473
void setDefaultVisible(const bool save)
Definition: window.h:288
std::string mCaption
Definition: window.h:608
void setDefaultSize()
Definition: window.cpp:1198
void loadWindowState()
Definition: window.cpp:1087
void setStickyButton(const bool flag)
Definition: window.cpp:761
Configuration config
Configuration paths
#define MSDL_CreateRGBSurface(flags, w, h, d, r, g, b, a)
Definition: debug.h:55
#define MSDL_FreeSurface(surface)
Definition: debug.h:54
Viewport * viewport
Definition: viewport.cpp:36
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define _(s)
Definition: gettext.h:35
ImageHelper * imageHelper
Definition: imagehelper.cpp:44
#define nullptr
Definition: localconsts.h:45
#define CHECKLISTENERS
Definition: localconsts.h:277
LocalPlayer * localPlayer
uint32_t data
uint32_t party
Minimap * minimap
Definition: minimap.cpp:62
const bool Modal_false
Definition: modal.h:30
@ Mercenary
Definition: actortype.h:38
@ Homunculus
Definition: actortype.h:39
@ SkillUnit
Definition: actortype.h:40
@ Elemental
Definition: actortype.h:41
@ FloorItem
Definition: actortype.h:34
@ PLAYERWALL
Definition: blockmask.h:36
int size()
Definition: emotedb.cpp:306
Image * getImage(const std::string &idPath)
Definition: imageloader.cpp:86
@ PORTAL_HIGHLIGHT
Definition: usercolorid.h:79
bool exists(std::string name)
Definition: fs.cpp:124
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
PopupManager * popupManager
PopupMenu * popupMenu
Definition: popupmenu.cpp:103
Settings settings
Definition: settings.cpp:32
SetupWindow * setupWindow
Definition: setupwindow.cpp:64
#define STD_MOVE(var)
Definition: stdmove.h:28
std::string pathJoin(std::string str1, const std::string &str2)
unsigned char blockmask
Definition: metatile.h:52
TextPopup * textPopup
Definition: textpopup.cpp:33
UserColorId ::T UserColorIdT
Definition: usercolorid.h:99
UserPalette * userPalette
Definition: userpalette.cpp:34
bool Visible
Definition: visible.h:30
const bool Visible_false
Definition: visible.h:30
const bool Visible_true
Definition: visible.h:30