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