1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2018 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
;
102 Color
= NLMISC::CRGBA::White
;
109 * Display of map and landmarks.
111 * There are several coordinate systems :
113 * - World coordinates : as usual
114 * - Map coordinates : In the [0, 1] range. [0, 0] is the upper left of map, and [1, 1] is the lower right.
115 * the corners of the map in world coordinates are given by their zone names (in the continent sheet)
116 * - Screen coordinates : in pixels
117 * - Window coordinates : the same as screen coordinate, but relative to that CInterfaceGroup
119 * \author Nicolas Vizerie
120 * \author Nevrax France
124 class CGroupMap
: public CInterfaceGroup
128 // external element to be displayed on the map
131 /** called when the element is added to the map. If the deco is an interface element, it could
132 * add itself to this group child
134 virtual void onAdd(CGroupMap
&/* owner */) {}
135 virtual void onRemove(CGroupMap
&/* owner */) {}
136 virtual void onPreRender(CGroupMap
&/* owner */) {}
137 /** Called when the map has been scrolled or scaled. The deco should update its pos here
140 virtual void onUpdate(CGroupMap
&/* owner */) {}
143 REFLECT_EXPORT_START(CGroupMap
, CInterfaceGroup
)
144 REFLECT_STRING("continent", getContinentName
, dummySet
);
145 REFLECT_STRING("texture", getMapTexture
, dummySet
);
146 REFLECT_LUA_METHOD("isIsland", luaIsIsland
);
147 REFLECT_LUA_METHOD("reload", luaReload
);
150 int luaReload(CLuaState
&ls
);
151 int luaIsIsland(CLuaState
&ls
);
154 CGroupMap(const TCtorParam
¶m
);
155 virtual ~CGroupMap();
156 // Add a decoration to the map. The map will call the 'onAdd' method. When this object is destroyed, it will call the 'onRemove' method
157 void addDeco(IDeco
*deco
);
158 // Remove a decoration from the map. This will also call the 'onRemove' method. It is up to the owner to delete it.
159 void removeDeco(IDeco
*deco
);
161 virtual void setActive (bool state
);
162 virtual void updateCoords();
163 virtual void checkCoords();
164 virtual void draw ();
165 virtual bool handleEvent (const NLGUI::CEventDescriptor
&event
);
166 virtual bool parse(xmlNodePtr cur
, CInterfaceGroup
* parentGroup
);
167 virtual bool getCtrlsUnder (sint32 x
, sint32 y
, sint32 clipX
, sint32 clipY
, sint32 clipW
, sint32 clipH
, std::vector
<CCtrlBase
*> &vICL
);
169 // Name of the map as filled in the ryzom.world file
170 void setMap(const std::string
&mapName
);
171 void setMap(SMap
*map
);
173 // return current continent
174 std::string
getContinentName() const;
175 // return currently displayed map texture
176 std::string
getMapTexture() const;
178 // reload current map texture
181 // pan the map of the given number of pixels
182 void pan(sint32 dx
, sint32 dy
);
184 // center the map on the player
185 void centerOnPlayer();
186 // center current map on world coords (if not out of map bounds)
187 void centerOnWorldPos(const NLMISC::CVector2f
&worldPos
);
189 void setPlayerPos(const NLMISC::CVector2f
&p
) { _PlayerPos
= p
; }
190 NLMISC::CVector2f
getPlayerPos() const { return _PlayerPos
; }
191 // test if player is currently panning the map
192 bool isPanning() const { return _Panning
; }
193 /** Change the scale. It will be clipped to the max possible value
194 * The center of the scale transformation must be given in the map coordinates.
196 void setScale(float newScale
, const NLMISC::CVector2f
¢er
);
197 /** Change the scale. It will be clipped to the max possible value
198 * The center of the scale is the center of current window
200 void setScale(float newScale
);
202 float getScale() const { return _UserScale
; }
203 /// add a user landmark (returns a pointer on its button).Coordinate are in the current map (not world coordinates)
204 CCtrlButton
*addUserLandMark(const NLMISC::CVector2f
&pos
, const ucstring
&title
, const CUserLandMark::EUserLandMarkType lmType
);
205 /// return current continent landmark by its index and type
206 CCtrlButton
* getLandmarkCtrl(const std::string
&lmType
, uint lmIndex
) const;
207 // remove a user landmark from a pointer on its button
208 void removeUserLandMark(CCtrlButton
*button
);
209 // update a user landmark from a pointer on its button
210 void updateUserLandMark(CCtrlButton
*button
, const ucstring
&newName
, const CUserLandMark::EUserLandMarkType lmType
);
211 // get a user landmark from a pointer on its button
212 CUserLandMark
getUserLandMark(CCtrlButton
*button
) const;
213 // get pos on the map of the last right click (in map coords)
214 NLMISC::CVector2f
getRightClickLastPos() const { return _RightClickLastPos
; }
215 // get number of user landmarks
216 uint
getNumUserLandMarks() const;
217 // get the LandMarksOptions for a given landmark index
218 CLandMarkOptions
getUserLandMarkOptions(uint32 lmindex
) const;
219 // target the given landmark
220 void targetLandmark(CCtrlButton
*lm
);
221 void targetLandmarkResult(uint32 index
);
222 // search matching landmark and target it. return true if landmark was targeted
223 bool targetLandmarkByName(const ucstring
&search
, bool startsWith
) const;
224 // get the world position of a landmark or return vector Null if not found
225 void getLandmarkPosition(const CCtrlButton
*lm
, NLMISC::CVector2f
&worldPos
);
227 //Remove and re-create UserLandMarks
228 void removeUserLandMarks();
229 void updateUserLandMarks();
230 void addUserLandMark(const NLMISC::CVector2f
&pos
, const ucstring
&title
, NLMISC::CRGBA color
);
231 void addUserRespawnPoint(const NLMISC::CVector2f
&pos
);
235 // set landmarks visibility based text query
236 void setLandmarkFilter(const std::string
&s
);
238 // set the selection axis pos & visibility
239 void setSelectionAxis(bool active
, const NLMISC::CVector2f
&worldPos
= NLMISC::CVector2f::Null
);
241 // 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,
242 // avoiding annoying flickering)
243 void worldToWindowSnapped(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
244 void worldToWindow(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
245 void mapToWindowSnapped(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
246 // convert a pos in world to a pos in the map (in the [0, 1] range)
247 void worldToMap(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
248 // convert a pos in world to a pos in map (coords are in [0, 1] in the map)
249 void mapToWorld(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
250 // convert a pos in window in a pos in screen
251 void windowToScreen(sint32
&destX
, sint32
&destY
, sint32 srcX
, sint32 srcY
) const;
252 // convert a pos in the map to a pos on screen
253 void mapToScreen(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
255 // convert a pos in the map to a pos relative to the current window (int result)
256 void mapToWindow(sint32
&px
, sint32
&py
, const NLMISC::CVector2f
&src
) const;
257 void mapToWindow(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
) const;
258 // convert a pos on screen to a pos in map
259 void screenToMap(NLMISC::CVector2f
&dest
, sint32 px
, sint32 py
) const;
260 // convert a pos on window to a pos in map
261 void windowToMap(NLMISC::CVector2f
&dest
, sint32 px
, sint32 py
) const;
262 float getMeterPerPixel() const { return _MeterPerPixel
; }
265 const NLMISC::CVector2f
&getVisibleWorldMin() const { return _VisibleWorldMin
; }
266 const NLMISC::CVector2f
&getVisibleWorldMax() const { return _VisibleWorldMax
; }
268 // compute pos of displayed map relative to this group (may be equal are smaller than this group extent
269 // depending on the scale.
270 void computeMapRectInsideGroup(sint32
&x
, sint32
&y
, sint32
&w
, sint32
&h
) const;
273 // From CInterfaceElement : scale and offset must persist between virtual desktops
274 virtual bool wantSerialConfig() const { return true; }
275 // From CInterfaceElement
276 virtual void serialConfig(NLMISC::IStream
&f
);
279 // Server set all valid respawn points
280 void addRespawnPoints(const CRespawnPointsMsg
&rpm
);
282 // add Ark landscape point
283 void addArkPoint(const CArkPoint
&point
);
285 std::string
getArkPowoMode() const { return _ArkPowoMode
; }
286 void setArkPowoMode(const std::string
&mode
) { _ArkPowoMode
= mode
; }
287 std::string
getArkPowoMapMenu() const { return _ArkPowoMapMenu
; }
288 void setArkPowoMapMenu(const std::string
&menu
) { _ArkPowoMapMenu
= menu
; }
290 bool isInDeathMode() { return _MapMode
== MapMode_Death
; }
292 sint32
getRespawnSelected() const;
293 void setRespawnSelected(sint32 nSpawnPointIndex
);
295 SMap
*getCurMap() { return _CurMap
; }
296 SMap
*getParentMap(SMap
*map
);
298 const NLMISC::CVector2f
&getWorldOffset() const { return _WorldOffset
; }
301 bool isIsland() const { return _IsIsland
; }
303 void updateClosestLandMarkMenu(const std::string
&menu
, const NLMISC::CVector2f
&pos
) const;
305 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
307 // A non rectangular button to click on zone of the map
308 class CPolyButton
: public CCtrlBase
312 virtual bool handleEvent (const NLGUI::CEventDescriptor
&event
);
313 virtual void updateCoords();
314 virtual void draw () {}
315 void drawPolyButton();
316 bool build(const NLLIGO::CPrimZone
&concavePoly
, CGroupMap
*pMap
, const std::string
&sID
);
317 bool contains(const NLMISC::CVector2f
&pos
);
319 NLLIGO::CPrimZone Zone
;
320 NLLIGO::CPrimZone ZoneReal
;
321 std::vector
<NLMISC::CPolygon2D
> Polys
; // Vertices in map pos
322 std::vector
<NLMISC::CPolygon2D
> PolysReal
; // Vertices in screen pos
325 static NL3D::UMaterial LineMat
;
327 typedef std::vector
<CPolyButton
*> TPolyButtonVect
;
328 // a button representing a location on the map
329 class CLandMarkButton
: public CCtrlButton
332 NLMISC::CVector2f Pos
;
333 CContLandMark::TContLMType Type
;
337 virtual bool handleEvent (const NLGUI::CEventDescriptor
& event
)
339 if (!HandleEvents
) return false;
340 return CCtrlButton::handleEvent(event
);
342 virtual bool isCapturable() const
346 virtual bool wantInstantContextHelp() const { return true; } // from CCtrlBase : avoid delay when the mouse is over
347 CLandMarkButton(const TCtorParam
¶m
)
350 Type
= CContLandMark::Unknown
;
356 typedef std::vector
<CLandMarkButton
*> TLandMarkButtonVect
;
359 class CLandMarkText
: public CViewText
362 NLMISC::CVector2f Pos
;
363 CContLandMark::TContLMType Type
;
366 CLandMarkText(const TCtorParam
¶m
)
369 Type
= CContLandMark::Unknown
;
374 typedef std::vector
<CLandMarkText
*> TLandMarkTextVect
;
376 float getActualMaxScale() const;
379 ///////////////////////
380 // MULTIMAP HANDLING //
381 ///////////////////////
383 // Logical information to display the map
384 CWorldSheet
*_WorldSheet
;
386 CContinent
*_CurContinent
; // the last continent for which the map was displayed (can be NULL if world)
387 NLMISC::CVector2f _MapMinCorner
; // In world coordinates
388 NLMISC::CVector2f _MapMaxCorner
;
389 std::string _MapTexture
; // currently displayed map texture
391 bool _IsIsland
; // true if current map is an island (island bitmap need not to be raised to the next
394 TPolyButtonVect _PolyButtons
;
396 //////////////////////////////
397 // MAP & PLAYER POS TEXTURE //
398 //////////////////////////////
400 std::string _PlayerPosTexName
;
401 // min height of the window
404 // offset of the map view (offset is in uv coords)
405 NLMISC::CVector2f _Offset
;
406 float _UserScale
; // user wanted scale
407 float _Scale
; // actual scale for drawing
410 float _MeterPerPixel
;
412 float _WorldToMapDeltaX
;
413 float _WorldToMapDeltaY
;
415 NLMISC::CVector2f _VisibleWorldMin
;
416 NLMISC::CVector2f _VisibleWorldMax
;
417 // continent map material
418 NL3D::UMaterial _MapMaterial
;
419 // continent map texture
420 NL3D::UTextureFile
*_MapTF
;
421 // player pos map material
422 NL3D::UMaterial _PlayerPosMaterial
;
423 // player pos map texture
424 NL3D::UTextureFile
*_PlayerPosTF
;
425 NL3D::UMaterial _FrustumMaterial
;
427 // continent map dimensions
428 uint32 _MapTexW
; // map texture width in pixels
429 uint32 _MapTexH
; // map texture height in pixels
430 uint32 _PlayerPosTexW
; // playerpos texture width in pixels
431 uint32 _PlayerPosTexH
; // playerpos texture height in pixels
432 float _URatio
; // == _MapTexW / nextPowerOf2(_MapTexW)
433 float _VRatio
; // == _MapTexH / nextPowerOf2(_MapTexH)
434 bool _MapLoadFailure
; // load failure for the map
435 bool _PlayerPosLoadFailure
; // load failure for the player pos sprite
437 NLMISC::CVector2f _PlayerPos
; // player pos ranging from 0.f to 1.f in the map
438 NLMISC::CVector2f _OldPlayerPos
; // old player pos in world
440 // position of map relative to its parent. Maybe 0 unless the map is centred
446 std::string _ArkPowoMode
;
447 std::string _ArkPowoMapMenu
;
448 NLMISC::CRGBA _FrustumViewColor
;
449 NLMISC::CRGBA _FrustumViewColorOver
;
450 float _FrustumOverBlendFactor
;
451 uint _FrustumViewBlendTimeInMs
;
454 CViewBitmap
*_SelectionAxisH
;
455 CViewBitmap
*_SelectionAxisV
;
463 NLMISC::CVector2f _RightClickLastPos
;
464 bool _Panning
; // does the user currently 'pan' the map ?
466 sint64 _PanStartDateInMs
;
467 sint64 _DeltaTimeBeforePanInMs
;
468 uint _DeltaPosBeforePan
;
470 sint32 _StartXForPaning
; // start pos for panning (in map)
471 sint32 _StartYForPaning
;
472 NLMISC::CVector2f _StartWorldOffsetForPaning
; // World Offset Panning
473 NLMISC::CVector2f _WorldOffset
;
479 // landmarks of continent
480 TLandMarkButtonVect _ContinentLM
;
481 TLandMarkTextVect _ContinentText
;
482 // landmarks from user
483 TLandMarkButtonVect _UserLM
;
484 // landmarks for mission (one for each db entry)
485 TLandMarkButtonVect _MissionLM
;
486 // landmark for target
487 CLandMarkButton
*_TargetLM
;
488 // landmark for home (user flat)
489 CLandMarkButton
*_HomeLM
;
490 // landmark for animals
491 TLandMarkButtonVect _AnimalLM
;
492 // landmark for teammates
493 TLandMarkButtonVect _TeammateLM
;
496 CLandMarkOptions _ContinentLMOptions
;
497 CLandMarkOptions _MissionLMOptions
;
498 CLandMarkOptions _UserLMOptions
;
499 CLandMarkOptions _TargetLMOptions
;
500 CLandMarkOptions _HomeLMOptions
;
501 CLandMarkOptions _AnimalLMOptions
;
502 CLandMarkOptions _AnimalStableLMOptions
;
503 CLandMarkOptions _AnimalDeadLMOptions
;
504 CLandMarkOptions _TeammateLMOptions
;
507 // last texts id for missions targets
508 std::vector
<sint32
> _MissionTargetTextIDs
;
509 // have the texts been received for mission targets ?
510 std::vector
<bool> _MissionTargetTextReceived
;
511 // ptr on db leaf for coordinates of special landmarks
512 NLMISC::CCDBNodeLeaf
*_TargetPos
;
513 NLMISC::CCDBNodeLeaf
*_HomePos
;
514 // Animals State for landMarks
515 std::vector
<NLMISC::CSmartPtr
<CAnimalPositionState
> > _AnimalPosStates
;
516 // Teammate State for landMarks
517 std::vector
<NLMISC::CSmartPtr
<CTeammatePositionState
> > _TeammatePosStates
;
518 // Mission State for landMarks
519 std::vector
<NLMISC::CSmartPtr
<CNamedEntityPositionState
> > _MissionPosStates
;
521 // ui id of compass for targetting
522 std::string _CompassId
;
525 typedef std::set
<IDeco
*> TDecos
;
529 std::vector
<ucstring
> _LandmarkFilter
;
530 struct SMatchedLandmark
532 SMatchedLandmark(const NLMISC::CVector2f pos
, const ucstring
&title
, CLandMarkOptions opts
)
533 : Pos(pos
), Title(title
), Options(opts
)
535 NLMISC::CVector2f Pos
;
538 CLandMarkOptions Options
;
540 std::vector
<SMatchedLandmark
> _MatchedLandmarks
;
542 //////////////////////
543 // Respawn handling //
544 // //////////////// //
554 std::vector
<CArkPoint
> _ArkPoints
;
555 CLandMarkOptions _RespawnLMOptions
;
556 // landmark for respawn
557 TLandMarkButtonVect _RespawnLM
;
558 sint32 _RespawnSelected
;
559 CViewBitmap
*_RespawnSelectedBitmap
;
560 std::string _RespawnButton
;
561 // Positions are coming from server
562 std::vector
<CRespawnPointsMsg::SRespawnPoint
> _RespawnPos
;
563 bool _RespawnPosReseted
;
564 CCtrlQuad
*_FrustumView
; // frustum on map for R2 editor
567 std::vector
<SMap
> _Islands
;
569 // guard against recursive calls
570 bool _LuaLoadMapEntered
;
573 void loadPlayerPos();
577 void updateContinentInfo();
578 /** update a list of landmarks
579 * This update their position on the map depending on offset and scale
581 void updateLandMarkList(TLandMarkButtonVect
&lm
);
582 void updateLandMarkTextList(TLandMarkTextVect
&lm
);
583 void updateMatchedLandmarks();
585 void removeLandMarks(TLandMarkButtonVect
&lm
);
586 /** create landmarks from the continent (and remove previous ones)
587 * this includes fixed and user landmarks
589 void createContinentLandMarks();
590 void createLMWidgets(const std::vector
<CContLandMark
> &lms
);
592 // add a landmark in a list
593 void addLandMark(TLandMarkButtonVect
&destList
, const NLMISC::CVector2f
&pos
, const ucstring
&title
, const CLandMarkOptions
&options
);
594 // Create a landmark button, but do not add it to this group
595 CLandMarkButton
*createLandMarkButton(const CLandMarkOptions
&options
);
596 // Create a Ark landmark button, but do not add it to this group
597 CLandMarkButton
*createArkPointButton(const CArkPoint
&point
);
599 // update a landmark button
600 void updateLandMarkButton(CLandMarkButton
*lmb
, const CLandMarkOptions
&options
);
602 // Test title against landmark filter
603 bool filterLandmark(const ucstring
&title
) const;
604 bool filterLandmark(const ucstring
&title
, const std::vector
<ucstring
> filter
, bool startsWith
= false) const;
606 // return closest landmark which matches (case insensitive) search string
607 // center position must be in world coordindates
608 CLandMarkButton
* findClosestLandmark(const NLMISC::CVector2f
¢er
, const ucstring
&search
, bool startsWith
, const TLandMarkButtonVect
&landmarks
, float &closest
) const;
609 CLandMarkText
* findClosestLandmark(const NLMISC::CVector2f
¢er
, const ucstring
&search
, bool startsWith
, const TLandMarkTextVect
&landmarks
, float &closest
) const;
611 // update the scale depending on the window size and the user scale
614 // compute real scale from user scale (this takes in account the size of the window)
615 float computeRealScaleFromUserScale(float userScale
) const;
617 // compute the user scale needed to reach the given real scale on screen (this takes in account the size of the window)
618 float computeUserScaleFromRealScale(float realScale
) const;
620 // eval map offset from its parent depending on scale
621 void evalMapOffset(float userScale
, float &scale
, sint32
&x
, sint32
&y
) const;
623 // compute _Offset from the _WorldOffset. Then clamp so that region outside the map can't be seen
624 void computeOffsets(const NLMISC::CVector2f
¢erPos
);
625 void computeOffsets();
627 void updatePlayerPos();
628 // clamp offsets & change window size if necessary
631 void updateButtonPos(CLandMarkButton
&dest
) const;
632 // Update a landmark position from position given from the db as two int32's (before they're divided by 1000)
633 void updateLMPosFromDBPos(CLandMarkButton
*dest
, sint32 x
, sint32 y
);
634 // compute uv rect for current map (not including cropping)
635 void computeUVRect(float &minU
, float &minV
, float &maxU
, float &maxV
) const;
637 void updateSelectionAxisSize();
638 CViewBitmap
*newSelectionAxis(NLMISC::CRGBA color
);
639 void computeFrustumQuad(NLMISC::CQuad
&fruQuad
) const;