1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #ifndef CL_GROUP_MAP_CL
24 #define CL_GROUP_MAP_CL
26 #include "nel/misc/vector_2f.h"
27 #include "nel/misc/ucstring.h"
29 #include "../client_sheets/world_sheet.h"
31 #include "nel/gui/interface_group.h"
32 #include "nel/gui/ctrl_button.h"
33 #include "nel/gui/view_bitmap.h"
34 #include "nel/gui/view_text.h"
35 #include "animal_position_state.h"
36 #include "../continent.h"
63 #define MISSIONS_DB_PATH "SERVER:MISSIONS"
64 #define GROUP_MISSIONS_DB_PATH "SERVER:GROUP:MISSIONS"
65 #define COMPASS_DB_PATH "SERVER:COMPASS"
67 const float RYZOM_MAP_MAX_SCALE
= 8.f
;
70 class CLandMarkOptions
73 std::string LandMarkTexNormal
;
74 std::string LandMarkTexOver
;
75 std::string LandMarkTexPushed
;
76 NLMISC::CRGBA ColorNormal
;
77 NLMISC::CRGBA ColorOver
;
78 NLMISC::CRGBA ColorPushed
;
79 std::string LandMarkMenu
;
83 ColorNormal
= ColorOver
= ColorPushed
= NLMISC::CRGBA::White
;
94 std::string LeftClickAction
;
95 std::string LeftClickParam
;
96 std::string RightClickAction
;
97 std::string RightClickParam
;
98 std::string OverClickAction
;
99 std::string OverClickParam
;
104 Color
= NLMISC::CRGBA::White
;
111 * Display of map and landmarks.
113 * There are several coordinate systems :
115 * - World coordinates : as usual
116 * - Map coordinates : In the [0, 1] range. [0, 0] is the upper left of map, and [1, 1] is the lower right.
117 * the corners of the map in world coordinates are given by their zone names (in the continent sheet)
118 * - Screen coordinates : in pixels
119 * - Window coordinates : the same as screen coordinate, but relative to that CInterfaceGroup
121 * \author Nicolas Vizerie
122 * \author Nevrax France
126 class CGroupMap
: public CInterfaceGroup
130 // external element to be displayed on the map
133 /** called when the element is added to the map. If the deco is an interface element, it could
134 * add itself to this group child
136 virtual void onAdd(CGroupMap
&/* owner */) {}
137 virtual void onRemove(CGroupMap
&/* owner */) {}
138 virtual void onPreRender(CGroupMap
&/* owner */) {}
139 /** Called when the map has been scrolled or scaled. The deco should update its pos here
142 virtual void onUpdate(CGroupMap
&/* owner */) {}
145 REFLECT_EXPORT_START(CGroupMap
, CInterfaceGroup
)
146 REFLECT_STRING("continent", getContinentName
, dummySet
);
147 REFLECT_STRING("texture", getMapTexture
, dummySet
);
148 REFLECT_LUA_METHOD("isIsland", luaIsIsland
);
149 REFLECT_LUA_METHOD("reload", luaReload
);
152 int luaReload(CLuaState
&ls
);
153 int luaIsIsland(CLuaState
&ls
);
156 CGroupMap(const TCtorParam
¶m
);
157 virtual ~CGroupMap();
158 // Add a decoration to the map. The map will call the 'onAdd' method. When this object is destroyed, it will call the 'onRemove' method
159 void addDeco(IDeco
*deco
);
160 // Remove a decoration from the map. This will also call the 'onRemove' method. It is up to the owner to delete it.
161 void removeDeco(IDeco
*deco
);
163 virtual void setActive (bool state
);
164 virtual void updateCoords();
165 virtual void checkCoords();
166 virtual void draw ();
167 virtual bool handleEvent (const NLGUI::CEventDescriptor
&event
);
168 virtual bool parse(xmlNodePtr cur
, CInterfaceGroup
* parentGroup
);
169 virtual bool getCtrlsUnder (sint32 x
, sint32 y
, sint32 clipX
, sint32 clipY
, sint32 clipW
, sint32 clipH
, std::vector
<CCtrlBase
*> &vICL
);
171 // Name of the map as filled in the ryzom.world file
172 void setMap(const std::string
&mapName
);
173 void setMap(SMap
*map
);
175 // return current continent
176 std::string
getContinentName() const;
177 // return currently displayed map texture
178 std::string
getMapTexture() const;
180 // reload current map texture
183 // pan the map of the given number of pixels
184 void pan(sint32 dx
, sint32 dy
);
186 // center the map on the player
187 void centerOnPlayer();
188 // center current map on world coords (if not out of map bounds)
189 void centerOnWorldPos(const NLMISC::CVector2f
&worldPos
);
191 void setPlayerPos(const NLMISC::CVector2f
&p
) { _PlayerPos
= p
; }
192 NLMISC::CVector2f
getPlayerPos() const { return _PlayerPos
; }
193 // test if player is currently panning the map
194 bool isPanning() const { return _Panning
; }
195 /** Change the scale. It will be clipped to the max possible value
196 * The center of the scale transformation must be given in the map coordinates.
198 void setScale(float newScale
, const NLMISC::CVector2f
¢er
);
199 /** Change the scale. It will be clipped to the max possible value
200 * The center of the scale is the center of current window
202 void setScale(float newScale
);
204 float getScale() const { return _UserScale
; }
205 /// add a user landmark (returns a pointer on its button).Coordinate are in the current map (not world coordinates)
206 CCtrlButton
*addUserLandMark(const NLMISC::CVector2f
&pos
, const ucstring
&title
, const CUserLandMark::EUserLandMarkType lmType
);
207 /// return current continent landmark by its index and type
208 CCtrlButton
* getLandmarkCtrl(const std::string
&lmType
, uint lmIndex
) const;
209 // remove a user landmark from a pointer on its button
210 void removeUserLandMark(CCtrlButton
*button
);
211 // update a user landmark from a pointer on its button
212 void updateUserLandMark(CCtrlButton
*button
, const ucstring
&newName
, const CUserLandMark::EUserLandMarkType lmType
);
213 // get a user landmark from a pointer on its button
214 CUserLandMark
getUserLandMark(CCtrlButton
*button
) const;
215 // get pos on the map of the last right click (in map coords)
216 NLMISC::CVector2f
getRightClickLastPos() const { return _RightClickLastPos
; }
217 // get number of user landmarks
218 uint
getNumUserLandMarks() const;
219 // get the LandMarksOptions for a given landmark index
220 CLandMarkOptions
getUserLandMarkOptions(uint32 lmindex
) const;
221 // target the given landmark
222 void targetLandmark(CCtrlButton
*lm
);
223 void targetLandmarkResult(uint32 index
);
224 // search matching landmark and target it. return true if landmark was targeted
225 bool targetLandmarkByName(const ucstring
&search
, bool startsWith
) const;
226 // get the world position of a landmark or return vector Null if not found
227 void getLandmarkPosition(const CCtrlButton
*lm
, NLMISC::CVector2f
&worldPos
);
229 //Remove and re-create UserLandMarks
230 void removeUserLandMarks();
231 void updateUserLandMarks();
232 void addUserLandMark(const NLMISC::CVector2f
&pos
, const ucstring
&title
, NLMISC::CRGBA color
);
233 void addUserRespawnPoint(const NLMISC::CVector2f
&pos
);
237 // set landmarks visibility based text query
238 void setLandmarkFilter(const std::string
&s
);
240 // set the selection axis pos & visibility
241 void setSelectionAxis(bool active
, const NLMISC::CVector2f
&worldPos
= NLMISC::CVector2f::Null
);
243 // convert a pos in world to a pos in the window, snapped to the best pixel (-> all elements jump to the next pixel at the same time when the map is panned,
244 // avoiding annoying flickering)
245 void worldToWindowSnapped(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
246 void worldToWindow(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
247 void mapToWindowSnapped(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
248 // convert a pos in world to a pos in the map (in the [0, 1] range)
249 void worldToMap(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
250 // convert a pos in world to a pos in map (coords are in [0, 1] in the map)
251 void mapToWorld(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
252 // convert a pos in window in a pos in screen
253 void windowToScreen(sint32
&destX
, sint32
&destY
, sint32 srcX
, sint32 srcY
) const;
254 // convert a pos in the map to a pos on screen
255 void mapToScreen(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
257 // convert a pos in the map to a pos relative to the current window (int result)
258 void mapToWindow(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
259 void mapToWindow(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
260 // convert a pos on screen to a pos in map
261 void screenToMap(NLMISC::CVector2f
&dest
, sint32 px
, sint32 py
) const;
262 // convert a pos on window to a pos in map
263 void windowToMap(NLMISC::CVector2f
&dest
, sint32 px
, sint32 py
) const;
264 float getMeterPerPixel() const { return _MeterPerPixel
; }
267 const NLMISC::CVector2f
&getVisibleWorldMin() const { return _VisibleWorldMin
; }
268 const NLMISC::CVector2f
&getVisibleWorldMax() const { return _VisibleWorldMax
; }
270 // compute pos of displayed map relative to this group (may be equal are smaller than this group extent
271 // depending on the scale.
272 void computeMapRectInsideGroup(sint32
&x
, sint32
&y
, sint32
&w
, sint32
&h
) const;
275 // From CInterfaceElement : scale and offset must persist between virtual desktops
276 virtual bool wantSerialConfig() const { return true; }
277 // From CInterfaceElement
278 virtual void serialConfig(NLMISC::IStream
&f
);
281 // Server set all valid respawn points
282 void addRespawnPoints(const CRespawnPointsMsg
&rpm
);
284 // add Ark landscape point
285 void addArkPoint(const CArkPoint
&point
);
287 std::string
getArkPowoMode() const { return _ArkPowoMode
; }
288 void setArkPowoMode(const std::string
&mode
) { _ArkPowoMode
= mode
; }
289 std::string
getArkPowoMapMenu() const { return _ArkPowoMapMenu
; }
290 void setArkPowoMapMenu(const std::string
&menu
) { _ArkPowoMapMenu
= menu
; }
292 bool isInDeathMode() { return _MapMode
== MapMode_Death
; }
294 sint32
getRespawnSelected() const;
295 void setRespawnSelected(sint32 nSpawnPointIndex
);
297 SMap
*getCurMap() { return _CurMap
; }
298 SMap
*getParentMap(SMap
*map
);
300 const NLMISC::CVector2f
&getWorldOffset() const { return _WorldOffset
; }
303 bool isIsland() const { return _IsIsland
; }
305 void updateClosestLandMarkMenu(const std::string
&menu
, const NLMISC::CVector2f
&pos
) const;
307 // show/hide all user landmarks
308 void setUserLandMarkVisible(bool state
);
309 bool getUserLandMarkVisible() const { return _UserLandMarkVisible
; };
311 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
313 // A non rectangular button to click on zone of the map
314 class CPolyButton
: public CCtrlBase
318 virtual bool handleEvent (const NLGUI::CEventDescriptor
&event
);
319 virtual void updateCoords();
320 virtual void draw () {}
321 void drawPolyButton();
322 bool build(const NLLIGO::CPrimZone
&concavePoly
, CGroupMap
*pMap
, const std::string
&sID
);
323 bool contains(const NLMISC::CVector2f
&pos
);
325 NLLIGO::CPrimZone Zone
;
326 NLLIGO::CPrimZone ZoneReal
;
327 std::vector
<NLMISC::CPolygon2D
> Polys
; // Vertices in map pos
328 std::vector
<NLMISC::CPolygon2D
> PolysReal
; // Vertices in screen pos
331 static NL3D::UMaterial LineMat
;
333 typedef std::vector
<CPolyButton
*> TPolyButtonVect
;
334 // a button representing a location on the map
335 class CLandMarkButton
: public CCtrlButton
338 NLMISC::CVector2f Pos
;
339 CContLandMark::TContLMType Type
;
343 virtual bool handleEvent (const NLGUI::CEventDescriptor
& event
)
345 if (!HandleEvents
) return false;
346 return CCtrlButton::handleEvent(event
);
348 virtual bool isCapturable() const
352 virtual bool wantInstantContextHelp() const { return true; } // from CCtrlBase : avoid delay when the mouse is over
353 CLandMarkButton(const TCtorParam
¶m
)
356 Type
= CContLandMark::Unknown
;
362 typedef std::vector
<CLandMarkButton
*> TLandMarkButtonVect
;
365 class CLandMarkText
: public CViewText
368 NLMISC::CVector2f Pos
;
369 CContLandMark::TContLMType Type
;
372 CLandMarkText(const TCtorParam
¶m
)
375 Type
= CContLandMark::Unknown
;
380 typedef std::vector
<CLandMarkText
*> TLandMarkTextVect
;
382 float getActualMaxScale() const;
385 ///////////////////////
386 // MULTIMAP HANDLING //
387 ///////////////////////
389 // Logical information to display the map
390 CWorldSheet
*_WorldSheet
;
392 CContinent
*_CurContinent
; // the last continent for which the map was displayed (can be NULL if world)
393 NLMISC::CVector2f _MapMinCorner
; // In world coordinates
394 NLMISC::CVector2f _MapMaxCorner
;
395 std::string _MapTexture
; // currently displayed map texture
397 bool _IsIsland
; // true if current map is an island (island bitmap need not to be raised to the next
400 TPolyButtonVect _PolyButtons
;
402 //////////////////////////////
403 // MAP & PLAYER POS TEXTURE //
404 //////////////////////////////
406 std::string _PlayerPosTexName
;
407 // min height of the window
410 // offset of the map view (offset is in uv coords)
411 NLMISC::CVector2f _Offset
;
412 float _UserScale
; // user wanted scale
413 float _Scale
; // actual scale for drawing
416 float _MeterPerPixel
;
418 float _WorldToMapDeltaX
;
419 float _WorldToMapDeltaY
;
421 NLMISC::CVector2f _VisibleWorldMin
;
422 NLMISC::CVector2f _VisibleWorldMax
;
423 // continent map material
424 NL3D::UMaterial _MapMaterial
;
425 // continent map texture
426 NL3D::UTextureFile
*_MapTF
;
427 // player pos map material
428 NL3D::UMaterial _PlayerPosMaterial
;
429 // player pos map texture
430 NL3D::UTextureFile
*_PlayerPosTF
;
431 NL3D::UMaterial _FrustumMaterial
;
433 // continent map dimensions
434 uint32 _MapTexW
; // map texture width in pixels
435 uint32 _MapTexH
; // map texture height in pixels
436 uint32 _PlayerPosTexW
; // playerpos texture width in pixels
437 uint32 _PlayerPosTexH
; // playerpos texture height in pixels
438 float _URatio
; // == _MapTexW / nextPowerOf2(_MapTexW)
439 float _VRatio
; // == _MapTexH / nextPowerOf2(_MapTexH)
440 bool _MapLoadFailure
; // load failure for the map
441 bool _PlayerPosLoadFailure
; // load failure for the player pos sprite
443 NLMISC::CVector2f _PlayerPos
; // player pos ranging from 0.f to 1.f in the map
444 NLMISC::CVector2f _OldPlayerPos
; // old player pos in world
446 // position of map relative to its parent. Maybe 0 unless the map is centred
452 std::string _ArkPowoMode
;
453 std::string _ArkPowoMapMenu
;
454 NLMISC::CRGBA _FrustumViewColor
;
455 NLMISC::CRGBA _FrustumViewColorOver
;
456 float _FrustumOverBlendFactor
;
457 uint _FrustumViewBlendTimeInMs
;
460 CViewBitmap
*_SelectionAxisH
;
461 CViewBitmap
*_SelectionAxisV
;
469 NLMISC::CVector2f _RightClickLastPos
;
470 bool _Panning
; // does the user currently 'pan' the map ?
472 sint64 _PanStartDateInMs
;
473 sint64 _DeltaTimeBeforePanInMs
;
474 uint _DeltaPosBeforePan
;
476 sint32 _StartXForPaning
; // start pos for panning (in map)
477 sint32 _StartYForPaning
;
478 NLMISC::CVector2f _StartWorldOffsetForPaning
; // World Offset Panning
479 NLMISC::CVector2f _WorldOffset
;
485 // if false, user landmarks are not drawn
486 bool _UserLandMarkVisible
;
488 // landmarks of continent
489 TLandMarkButtonVect _ContinentLM
;
490 TLandMarkTextVect _ContinentText
;
491 // landmarks from user
492 TLandMarkButtonVect _UserLM
;
493 // landmarks for mission (one for each db entry)
494 TLandMarkButtonVect _MissionLM
;
495 // landmark for target
496 CLandMarkButton
*_TargetLM
;
497 // landmark for home (user flat)
498 CLandMarkButton
*_HomeLM
;
499 // landmark for animals
500 TLandMarkButtonVect _AnimalLM
;
501 // landmark for teammates
502 TLandMarkButtonVect _TeammateLM
;
505 CLandMarkOptions _ContinentLMOptions
;
506 CLandMarkOptions _MissionLMOptions
;
507 CLandMarkOptions _UserLMOptions
;
508 CLandMarkOptions _TargetLMOptions
;
509 CLandMarkOptions _HomeLMOptions
;
510 CLandMarkOptions _AnimalLMOptions
;
511 CLandMarkOptions _AnimalStableLMOptions
;
512 CLandMarkOptions _AnimalDeadLMOptions
;
513 CLandMarkOptions _TeammateLMOptions
;
516 // last texts id for missions targets
517 std::vector
<sint32
> _MissionTargetTextIDs
;
518 // have the texts been received for mission targets ?
519 std::vector
<bool> _MissionTargetTextReceived
;
520 // ptr on db leaf for coordinates of special landmarks
521 NLMISC::CCDBNodeLeaf
*_TargetPos
;
522 NLMISC::CCDBNodeLeaf
*_HomePos
;
523 // Animals State for landMarks
524 std::vector
<NLMISC::CSmartPtr
<CAnimalPositionState
> > _AnimalPosStates
;
525 // Teammate State for landMarks
526 std::vector
<NLMISC::CSmartPtr
<CTeammatePositionState
> > _TeammatePosStates
;
527 // Mission State for landMarks
528 std::vector
<NLMISC::CSmartPtr
<CNamedEntityPositionState
> > _MissionPosStates
;
530 // ui id of compass for targetting
531 std::string _CompassId
;
534 typedef std::set
<IDeco
*> TDecos
;
538 std::vector
<ucstring
> _LandmarkFilter
;
539 struct SMatchedLandmark
541 SMatchedLandmark(const NLMISC::CVector2f pos
, const ucstring
&title
, CLandMarkOptions opts
)
542 : Pos(pos
), Title(title
), Options(opts
)
544 NLMISC::CVector2f Pos
;
547 CLandMarkOptions Options
;
549 std::vector
<SMatchedLandmark
> _MatchedLandmarks
;
551 //////////////////////
552 // Respawn handling //
553 // //////////////// //
563 std::vector
<CArkPoint
> _ArkPoints
;
564 CLandMarkOptions _RespawnLMOptions
;
565 // landmark for respawn
566 TLandMarkButtonVect _RespawnLM
;
567 sint32 _RespawnSelected
;
568 CViewBitmap
*_RespawnSelectedBitmap
;
569 std::string _RespawnButton
;
570 // Positions are coming from server
571 std::vector
<CRespawnPointsMsg::SRespawnPoint
> _RespawnPos
;
572 bool _RespawnPosReseted
;
573 CCtrlQuad
*_FrustumView
; // frustum on map for R2 editor
576 std::vector
<SMap
> _Islands
;
578 // guard against recursive calls
579 bool _LuaLoadMapEntered
;
582 void loadPlayerPos();
586 void updateContinentInfo();
587 /** update a list of landmarks
588 * This update their position on the map depending on offset and scale
590 void updateLandMarkList(TLandMarkButtonVect
&lm
);
591 void updateLandMarkTextList(TLandMarkTextVect
&lm
);
592 void updateMatchedLandmarks();
594 void removeLandMarks(TLandMarkButtonVect
&lm
);
595 /** create landmarks from the continent (and remove previous ones)
596 * this includes fixed and user landmarks
598 void createContinentLandMarks();
599 void createLMWidgets(const std::vector
<CContLandMark
> &lms
);
601 // add a landmark in a list
602 void addLandMark(TLandMarkButtonVect
&destList
, const NLMISC::CVector2f
&pos
, const ucstring
&title
, const CLandMarkOptions
&options
);
603 // Create a landmark button, but do not add it to this group
604 CLandMarkButton
*createLandMarkButton(const CLandMarkOptions
&options
);
605 // Create a Ark landmark button, but do not add it to this group
606 CLandMarkButton
*createArkPointButton(const CArkPoint
&point
);
608 // update a landmark button
609 void updateLandMarkButton(CLandMarkButton
*lmb
, const CLandMarkOptions
&options
);
611 // Test title against landmark filter
612 bool filterLandmark(const ucstring
&title
) const;
613 bool filterLandmark(const ucstring
&title
, const std::vector
<ucstring
> filter
, bool startsWith
= false) const;
615 // return closest landmark which matches (case insensitive) search string
616 // center position must be in world coordindates
617 CLandMarkButton
* findClosestLandmark(const NLMISC::CVector2f
¢er
, const ucstring
&search
, bool startsWith
, const TLandMarkButtonVect
&landmarks
, float &closest
) const;
618 CLandMarkText
* findClosestLandmark(const NLMISC::CVector2f
¢er
, const ucstring
&search
, bool startsWith
, const TLandMarkTextVect
&landmarks
, float &closest
) const;
620 // update the scale depending on the window size and the user scale
623 // compute real scale from user scale (this takes in account the size of the window)
624 float computeRealScaleFromUserScale(float userScale
) const;
626 // compute the user scale needed to reach the given real scale on screen (this takes in account the size of the window)
627 float computeUserScaleFromRealScale(float realScale
) const;
629 // eval map offset from its parent depending on scale
630 void evalMapOffset(float userScale
, float &scale
, sint32
&x
, sint32
&y
) const;
632 // compute _Offset from the _WorldOffset. Then clamp so that region outside the map can't be seen
633 void computeOffsets(const NLMISC::CVector2f
¢erPos
);
634 void computeOffsets();
636 void updatePlayerPos();
637 // clamp offsets & change window size if necessary
640 void updateButtonPos(CLandMarkButton
&dest
) const;
641 // Update a landmark position from position given from the db as two int32's (before they're divided by 1000)
642 void updateLMPosFromDBPos(CLandMarkButton
*dest
, sint32 x
, sint32 y
);
643 // compute uv rect for current map (not including cropping)
644 void computeUVRect(float &minU
, float &minV
, float &maxU
, float &maxV
) const;
646 void updateSelectionAxisSize();
647 CViewBitmap
*newSelectionAxis(NLMISC::CRGBA color
);
648 void computeFrustumQuad(NLMISC::CQuad
&fruQuad
) const;