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-2017 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 
186  if (minimapName.empty() && VirtFs::exists(tempname))
187  minimapName = tempname;
188 
189  if (minimapName.empty())
190  {
191  tempname = pathJoin("graphics/minimaps",
192  map->getFilename()).append(".png");
193  if (VirtFs::exists(tempname))
194  minimapName = STD_MOVE(tempname);
195  }
196 
197  if (!minimapName.empty())
198  mMapImage = Loader::getImage(minimapName);
199  else
200  mMapImage = nullptr;
201  mCustomMapImage = false;
202  }
203  }
204 
205  if ((mMapImage != nullptr) && (map != nullptr))
206  {
207  const int width = mMapImage->mBounds.w + 2 * getPadding();
208  const int height = mMapImage->mBounds.h
210  const int mapWidth = mMapImage->mBounds.w < 100 ? width : 100;
211  const int mapHeight = mMapImage->mBounds.h < 100 ? height : 100;
212  const int minWidth = mapWidth > 310 ? 310 : mapWidth;
213  const int minHeight = mapHeight > 220 ? 220 : mapHeight;
214 
215  setMinWidth(minWidth);
216  setMinHeight(minHeight);
217 
218  mWidthProportion = static_cast<float>(
219  mMapImage->mBounds.w) / static_cast<float>(map->getWidth());
220  mHeightProportion = static_cast<float>(
221  mMapImage->mBounds.h) / static_cast<float>(map->getHeight());
222 
223  setMaxWidth(width);
224  setMaxHeight(height);
225  if (mAutoResize)
226  {
227  setWidth(width);
228  setHeight(height);
229  }
230 
231  const Rect &rect = mDimension;
232  setDefaultSize(rect.x, rect.y, rect.width, rect.height);
234 
235  if (mShow)
237  }
238  else
239  {
240  if (!isSticky())
242  }
243  BLOCK_END("Minimap::setMap")
244 }
245 
247 {
250 }
251 
252 void Minimap::draw(Graphics *const graphics)
253 {
254  BLOCK_START("Minimap::draw")
255 
256  Window::draw(graphics);
257  draw2(graphics);
258 }
259 
260 void Minimap::safeDraw(Graphics *const graphics)
261 {
262  BLOCK_START("Minimap::draw")
263 
264  Window::safeDraw(graphics);
265  draw2(graphics);
266 }
267 
268 void Minimap::draw2(Graphics *const graphics)
269 {
270  if (userPalette == nullptr ||
271  localPlayer == nullptr ||
272  viewport == nullptr)
273  {
274  BLOCK_END("Minimap::draw")
275  return;
276  }
277 
278  const Rect a = getChildrenArea();
279 
280  graphics->pushClipArea(a);
281 
282  if (actorManager == nullptr)
283  {
284  BLOCK_END("Minimap::draw")
285  return;
286  }
287 
288  mMapOriginX = 0;
289  mMapOriginY = 0;
290 
291  if (mMapImage != nullptr)
292  {
293  const SDL_Rect &rect = mMapImage->mBounds;
294  const int w = rect.w;
295  const int h = rect.h;
296  if (w > a.width || h > a.height)
297  {
298  mMapOriginX = (a.width / 2) - (localPlayer->mPixelX +
300 
301  mMapOriginY = (a.height / 2) - (localPlayer->mPixelY +
303 
304  const int minOriginX = a.width - w;
305  const int minOriginY = a.height - h;
306 
307  if (mMapOriginX < minOriginX)
308  mMapOriginX = minOriginX;
309  if (mMapOriginY < minOriginY)
310  mMapOriginY = minOriginY;
311  if (mMapOriginX > 0)
312  mMapOriginX = 0;
313  if (mMapOriginY > 0)
314  mMapOriginY = 0;
315  }
316 
318  }
319 
320  const ActorSprites &actors = actorManager->getAll();
321  FOR_EACH (ActorSpritesConstIterator, it, actors)
322  {
323  if (((*it) == nullptr) || (*it)->getType() == ActorType::FloorItem)
324  continue;
325 
326  const Being *const being = static_cast<const Being *>(*it);
327  if (being == nullptr)
328  continue;
329 
330  int dotSize = 2;
332 
333  if (being == localPlayer)
334  {
335  type = UserColorId::SELF;
336  dotSize = 3;
337  }
338  else if (being->isGM())
339  {
340  type = UserColorId::GM;
341  }
342  else if (being->getGuild() == localPlayer->getGuild()
343  || being->getGuildName() == localPlayer->getGuildName())
344  {
345  type = UserColorId::GUILD;
346  }
347  else
348  {
349  switch (being->getType())
350  {
351  case ActorType::Monster:
352  type = UserColorId::MONSTER;
353  break;
354 
355  case ActorType::Npc:
356  type = UserColorId::NPC;
357  break;
358 
359  case ActorType::Portal:
361  break;
362 
363  case ActorType::Pet:
364  type = UserColorId::PET;
365  break;
367  type = UserColorId::MERCENARY;
368  break;
369 
372  break;
373 
375  type = UserColorId::SKILLUNIT;
376  break;
377  case ActorType::Avatar:
378  case ActorType::Unknown:
379  case ActorType::Player:
382  default:
383  continue;
384  }
385  }
386 
387  if (userPalette != nullptr)
388  graphics->setColor(userPalette->getColor(type));
389 
390  const int offsetHeight = CAST_S32(static_cast<float>(
391  dotSize - 1) * mHeightProportion);
392  const int offsetWidth = CAST_S32(static_cast<float>(
393  dotSize - 1) * mWidthProportion);
394  graphics->fillRectangle(Rect(
395  (being->mPixelX * mWidthProportion) / 32
396  + mMapOriginX - offsetWidth,
397  (being->mPixelY * mHeightProportion) / 32
398  + mMapOriginY - offsetHeight, dotSize, dotSize));
399  }
400 
401  if (localPlayer->isInParty())
402  {
403  const Party *const party = localPlayer->getParty();
404  if (party != nullptr)
405  {
406  const PartyMember *const m = party->getMember(
407  localPlayer->getName());
408  const Party::MemberList *const members = party->getMembers();
409  if (m != nullptr)
410  {
411  const std::string curMap = m->getMap();
412  Party::MemberList::const_iterator it = members->begin();
413  const Party::MemberList::const_iterator
414  it_end = members->end();
415  while (it != it_end)
416  {
417  const PartyMember *const member = *it;
418  if ((member != nullptr) && member->getMap() == curMap
419  && member->getOnline() && member != m)
420  {
421  if (userPalette != nullptr)
422  {
423  graphics->setColor(userPalette->getColor(
425  }
426 
427  const int offsetHeight = CAST_S32(
429  const int offsetWidth = CAST_S32(
431 
432  graphics->fillRectangle(Rect(
433  CAST_S32(member->getX()
434  * mWidthProportion) + mMapOriginX - offsetWidth,
435  CAST_S32(member->getY()
436  * mHeightProportion) + mMapOriginY - offsetHeight,
437  2, 2));
438  }
439  ++ it;
440  }
441  }
442  }
443  }
444 
445  const int gw = graphics->getWidth();
446  const int gh = graphics->getHeight();
447  int x = (localPlayer->mPixelX - (gw / 2)
449  * mWidthProportion / 32 + mMapOriginX;
450  int y = (localPlayer->mPixelY - (gh / 2)
453 
454  const int w = CAST_S32(static_cast<float>(
455  gw) * mWidthProportion / 32);
456  const int h = CAST_S32(static_cast<float>(
457  gh) * mHeightProportion / 32);
458 
459  if (w <= a.width)
460  {
461  if (x < 0 && (w != 0))
462  x = 0;
463  if (x + w > a.width)
464  x = a.width - w;
465  }
466  if (h <= a.height)
467  {
468  if (y < 0 && (h != 0))
469  y = 0;
470  if (y + h > a.height)
471  y = a.height - h;
472  }
473 
475  graphics->drawRectangle(Rect(x, y, w, h));
476  graphics->popClipArea();
477  BLOCK_END("Minimap::draw")
478 }
479 
481 {
482  if (event.getButton() == MouseButton::RIGHT)
483  return;
484  Window::mousePressed(event);
485 }
486 
488 {
489  Window::mouseReleased(event);
490 
491  if ((localPlayer == nullptr) || (popupManager == nullptr))
492  return;
493 
494  if (event.getButton() == MouseButton::LEFT)
495  {
496  int x = event.getX();
497  int y = event.getY();
498  screenToMap(x, y);
499 
500  localPlayer->navigateTo(x, y);
501  }
502  else if (event.getButton() == MouseButton::RIGHT)
503  {
504  int x = event.getX();
505  int y = event.getY();
506  screenToMap(x, y);
508  viewport->mMouseY,
509  x, y,
510  true);
511  }
512 }
513 
515 {
516  Window::mouseMoved(event);
517  const int x = event.getX();
518  const int y = event.getY();
519  const Rect &rect = mDimension;
520  textPopup->show(x + rect.x, y + rect.y, mCaption);
521 }
522 
524 {
525  Window::mouseExited(event);
526  textPopup->hide();
527 }
528 
529 void Minimap::screenToMap(int &x, int &y)
530 {
531  const Rect a = getChildrenArea();
534 }
535 
536 void Minimap::optionChanged(const std::string &name)
537 {
538  if (name == "autoresizeminimaps")
539  mAutoResize = config.getBoolValue("autoresizeminimaps");
540 }
void showMapPopup(const int x, const int y, const int x2, const int y2, const bool isMinimap)
Definition: popupmenu.cpp:796
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
void setDefaultSize()
Definition: window.cpp:1186
void screenToMap(int &x, int &y)
Definition: minimap.cpp:529
const Color & getColor(UserColorIdT type, const unsigned int alpha=255U)
Definition: userpalette.h:159
unsigned int getTitleBarHeight() const
Definition: window.h:514
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
int mMapOriginY
Definition: minimap.h:87
ActorSprites::const_iterator ActorSpritesConstIterator
Definition: actormanager.h:60
void setDefaultVisible(const bool save)
Definition: window.h:286
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:605
void loadWindowState()
Definition: window.cpp:1075
void mousePressed(MouseEvent &event)
Definition: minimap.cpp:480
virtual void resetToDefaultSize()
Definition: window.cpp:1247
Rect getChildrenArea()
Definition: window.cpp:1461
void setMaxHeight(const int height)
Definition: window.cpp:610
const Guild * getGuild(const std::string &guildName) const
Definition: being.cpp:1219
void toggle()
Definition: minimap.cpp:246
MouseButtonT getButton() const
Definition: mouseevent.h:113
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:579
Definition: window.h:98
#define MSDL_FreeSurface(surface)
Definition: debug.h:53
#define BLOCK_START(name)
Definition: perfomance.h:78
Configuration config
int getCameraRelativeY() const
Definition: viewport.h:142
PopupManager * popupManager
void mouseMoved(MouseEvent &event)
Definition: window.cpp:955
#define BLOCK_END(name)
Definition: perfomance.h:79
Party * getParty() const
Definition: being.h:325
void mouseMoved(MouseEvent &event)
Definition: minimap.cpp:514
virtual void popClipArea()
Definition: graphics.cpp:738
const std::string getProperty(const std::string &name, const std::string &def="") const
Definition: properties.h:58
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:268
int getHeight() const
Definition: map.h:168
void registerWindowForReset(Window *const window)
void mouseExited(MouseEvent &event)
Definition: minimap.cpp:523
static bool mShow
Definition: minimap.h:90
Settings settings
Definition: settings.cpp:31
virtual void setAlpha(const float alpha)
Definition: image.cpp:285
int x
Definition: rect.h:208
unsigned char blockmask
Definition: metatile.h:51
void hide()
Definition: popup.cpp:259
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:754
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:303
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:836
int mMapOriginX
Definition: minimap.h:86
PartyMember * getMember(const BeingId id) const
Definition: party.cpp:99
#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:476
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:316
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:233
void enableVisibleSound(bool b)
Definition: window.h:473
const std::string & getWindowName() const
Definition: window.h:359
void setMinHeight(const int height)
Definition: window.cpp:592
Definition: map.h:68
void draw(Graphics *const graphics)
Definition: minimap.cpp:252
#define STD_MOVE(var)
Definition: stdmove.h:27
int mMouseY
Definition: viewport.h:154
std::string mCaption
Definition: window.h:600
~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:162
void mouseReleased(MouseEvent &event)
Definition: window.cpp:895
void setSaveVisible(const bool save)
Definition: window.h:298
Configuration paths
MetaTile *const mMetaTiles
Definition: map.h:407
virtual void fillRectangle(const Rect &rectangle)=0
virtual void setVisible(Visible visible)
Definition: window.cpp:766
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:536
int getCameraRelativeX() const
Definition: viewport.h:139
void mousePressed(MouseEvent &event)
Definition: window.cpp:824
void mouseExited(MouseEvent &event)
Definition: window.cpp:912
const ActorSprites & getAll() const A_CONST
virtual void pushClipArea(const Rect &area)
Definition: graphics.cpp:676
void setResizable(const bool resize)
Definition: window.cpp:615
bool isSticky() const
Definition: window.h:251
SDL_Rect mBounds
Definition: image.h:210
SetupWindow * setupWindow
Definition: setupwindow.cpp:63
#define CHECKLISTENERS
Definition: localconsts.h:305
void setStickyButton(const bool flag)
Definition: window.cpp:749
const std::string getName() const
Definition: map.cpp:828
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:523
Definition: being.h:93
Image * mMapImage
Definition: minimap.h:85
float mWidthProportion
Definition: minimap.h:83
void decRef()
Definition: image.cpp:521
void setValue(const std::string &key, const std::string &value)
int getPadding() const
Definition: window.h:496
bool isGM() const
Definition: being.h:654
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:487
void safeDraw(Graphics *const graphics)
Definition: window.cpp:415
int getY() const
Definition: avatar.h:131
void safeDraw(Graphics *const graphics)
Definition: minimap.cpp:260
void setWindowName(const std::string &name)
Definition: window.h:353
Minimap * minimap
Definition: minimap.cpp:61
const std::string & getGuildName() const
Definition: being.h:260
#define MSDL_CreateRGBSurface(flags, w, h, d, r, g, b, a)
Definition: debug.h:54
std::set< ActorSprite * > ActorSprites
Definition: actormanager.h:56