1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 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>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "instance_map_deco.h"
24 #include "r2_config.h"
27 #include "nel/gui/ctrl_quad.h"
28 #include "nel/gui/group_container.h"
30 #include "nel/misc/i18n.h"
32 #include "game_share/scenario_entry_points.h"
34 using namespace NLMISC
;
43 // *********************************************************************************************************
44 void CInstanceMapDeco::CCtrlButtonEntity::getContextHelp(std::string
&help
) const
46 //H_AUTO(R2_CCtrlButtonEntity_getContextHelp)
47 help
= _Instance
.getDisplayName().toUtf8();
48 if (help
== NLMISC::CI18N::get("uiR2EDNoName"))
52 // *********************************************************************************************************
53 bool CInstanceMapDeco::CCtrlButtonEntity::handleEvent(const NLGUI::CEventDescriptor
&/* event */)
55 //H_AUTO(R2_CCtrlButtonEntity_handleEvent)
56 return false; // just a display with tooltip capability
59 // *********************************************************************************************************
60 CInstanceMapDeco::CInstanceMapDeco()
62 //H_AUTO(R2_CInstanceMapDeco_CInstanceMapDeco)
67 _GlowStar
[0] = _GlowStar
[1] = NULL
;
68 _GlowStarActive
= false;
69 _OrientBlendFactor
= 0.f
;
70 _LastCloseView
= false;
78 // *********************************************************************************************************
79 void CInstanceMapDeco::setDisplayedInstance(CInstance
*instance
, bool orientable
)
81 //H_AUTO(R2_CInstanceMapDeco_setDisplayedInstance)
83 nlassert(!_Instance
); // should be called once only
85 _Orientable
= orientable
;
88 // *********************************************************************************************************
89 CVector2f
CInstanceMapDeco::getWorldPos() const
91 //H_AUTO(R2_CInstanceMapDeco_getWorldPos)
93 CDisplayerVisual
*vd
= _Instance
->getDisplayerVisual();
94 if (!vd
) return CVector2f::Null
;
95 return vd
->getWorldPos2f();
98 // *********************************************************************************************************
99 void CInstanceMapDeco::invalidateCoords()
101 //H_AUTO(R2_CInstanceMapDeco_invalidateCoords)
105 nlassert(_OverInvalid
);
106 _Main
->invalidateCoords();
107 _Over
->invalidateCoords();
108 _OverInvalid
->invalidateCoords();
111 _GlowStar
[0]->invalidateCoords();
112 _GlowStar
[1]->invalidateCoords();
114 if (_Orient
) _Orient
->invalidateCoords();
117 // *********************************************************************************************************
118 CCtrlQuad
*CInstanceMapDeco::newQuad(CGroupMap
&owner
)
120 //H_AUTO(R2_CInstanceMapDeco_newQuad)
122 CViewBase::TCtorParam param
;
123 CCtrlQuad
*q
= new CCtrlQuad( param
);
125 q
->setModulateGlobalColor(false);
127 q
->setParent(&owner
);
132 // *********************************************************************************************************
133 void CInstanceMapDeco::onAdd(CGroupMap
&owner
)
135 //H_AUTO(R2_CInstanceMapDeco_onAdd)
139 nlassert(!_OverInvalid
);
140 _Main
= new CCtrlButtonEntity(*_Instance
);
141 _Main
->setPosRef(Hotspot_MM
);
142 _Main
->setParentPosRef(Hotspot_BL
);
143 _Main
->setModulateGlobalColorAll(false);
144 owner
.addCtrl(_Main
);
145 _Main
->setParent(&owner
);
146 _Main
->setRenderLayer(2);
147 _Main
->setId(owner
.getId() + ":" + _Instance
->getId());
148 _Main
->setActive(_Active
);
150 _Over
= newQuad(owner
);
151 _Over
->setRenderLayer(3);
152 _Over
->setActive(_Active
);
154 _OverInvalid
= newQuad(owner
);
155 _OverInvalid
->setRenderLayer(4);
156 _OverInvalid
->setActive(_Active
&& _InvalidPos
);
160 _Orient
= newQuad(owner
);
161 _Orient
->setTexture(CV_MapEntityOrientTexture
.get());
162 _Orient
->setRenderLayer(3);
163 _Orient
->setActive(_Active
);
166 CInterfaceGroup
*window
= owner
.getParentContainer();
169 CViewBase::TCtorParam param
;
171 for(uint k
= 0; k
< 2; ++k
)
173 _GlowStar
[k
] = new CCtrlQuad( param
);
174 _GlowStar
[k
]->setActive(false);
175 _GlowStar
[k
]->setModulateGlobalColor(false);
176 window
->addCtrl(_GlowStar
[k
]);
177 _GlowStar
[k
]->setParent(window
);
178 _GlowStar
[k
]->setAdditif(true);
179 _GlowStar
[k
]->setTexture(CV_MapGlowStarTexture
.get());
185 // *********************************************************************************************************
186 void CInstanceMapDeco::onRemove(CGroupMap
&owner
)
188 //H_AUTO(R2_CInstanceMapDeco_onRemove)
192 nlassert(_OverInvalid
);
193 owner
.delCtrl(_Main
);
195 owner
.delCtrl(_Over
);
197 owner
.delCtrl(_OverInvalid
);
201 owner
.delCtrl(_Orient
);
206 _GlowStar
[0]->getParent()->delCtrl(_GlowStar
[0]);
208 _GlowStar
[1]->getParent()->delCtrl(_GlowStar
[1]);
216 // *********************************************************************************************************
217 void CInstanceMapDeco::onPreRender(CGroupMap
&groupMap
)
219 //H_AUTO(R2_CInstanceMapDeco_onPreRender)
220 if (!_Active
) return;
226 // draw glowing stars on the edge to signal position well
227 for(uint k
= 0; k
< 2; ++k
)
229 _GlowStar
[k
]->setActive(true);
230 _GlowStar
[k
]->setQuad(_GlowStarPos
, CV_MapGlowStarSize
.get(), (float) (CV_MapGlowStarSpeed
[k
].get() * 0.001 * (double) T1
));
231 _GlowStar
[k
]->updateCoords();
238 bool closeView
= groupMap
.getMeterPerPixel() < CV_MapEntityCloseDist
.get();
239 CDisplayerVisual
*vd
= _Instance
->getDisplayerVisual();
242 if (_LastCloseView
!= closeView
)
244 _OrientBlendFactor
= closeView
? 0.5f
: 0.f
;
246 if (vd
->getRotateInProgress())
248 _OrientBlendFactor
= 1.f
;
252 // fade to default alpha
253 NLMISC::incrementalBlend(_OrientBlendFactor
, closeView
? 0.5f
: 0.f
, DT
* 1000.f
/ favoid0(CV_MapEntityOrientBlendTimeInMs
.get()));
258 _OrientBlendFactor
= 0.f
;
262 if (_OrientBlendFactor
== 0.f
)
264 _Orient
->setActive(false);
268 _Orient
->setActive(true);
269 _Orient
->setColorRGBA(CRGBA(255, 255, 255, (uint8
) (255 * _OrientBlendFactor
)));
272 groupMap
.worldToWindowSnapped(x
, y
, getWorldPos());
273 _Orient
->setQuad(CV_MapEntityOrientTexture
.get(), CVector((float) x
, (float) y
, 0.f
), vd
->getAngle(), closeView
? CV_MapEntityOrientOriginDist
.get() : CV_MapEntityOrientOriginDistSmall
.get());
274 _Orient
->updateCoords();
276 _LastCloseView
= closeView
;
278 if (_OverInvalid
->getActive())
280 _OverInvalid
->setColorRGBA(CTool::getInvalidPosColor());
284 // *********************************************************************************************************
285 void CInstanceMapDeco::onUpdate(CGroupMap
&groupMap
)
287 //H_AUTO(R2_CInstanceMapDeco_onUpdate)
288 if (!_Active
) return;
290 _GlowStarActive
= false;
291 if (!_Main
|| !_Over
|| !_OverInvalid
) return;
294 CVector2f worldPos
= getWorldPos();
295 // if not in current map then don't disply anything
296 CIslandCollision
&col
= getEditor().getIslandCollision();
297 R2::CScenarioEntryPoints::CCompleteIsland
*currIsland
= col
.getCurrIslandDesc();
300 if (!currIsland
->isIn(worldPos
))
306 groupMap
.worldToWindowSnapped(x
, y
, getWorldPos());
309 CDisplayerVisual
*vd
= _Instance
->getDisplayerVisual();
312 _Over
->setActive(false);
313 _OverInvalid
->setActive(false);
317 bool closeView
= _CloseTexture
.empty() ? false : groupMap
.getMeterPerPixel() < CV_MapEntityCloseDist
.get();
319 bool selected
= vd
->getDisplayFlag(CDisplayerVisual::FlagSelected
);
320 bool hasFocus
= vd
->getDisplayFlag(CDisplayerVisual::FlagHasFocus
);
322 setTextureAndFit(closeView
? _CloseTexture
: CV_MapEntitySmallTexture
.get());
323 _Main
->setColor((selected
&& ! closeView
) ? CV_MapEntitySelectColor
.get() : vd
->getDisplayModeColorInMap()); // if small icon, then change the icon color directly, because no over will be displayed
325 if (selected
|| hasFocus
)
327 // if the selection is out of the window, then draw an arrow to locate it
328 const CVector2f
&wmin
= groupMap
.getVisibleWorldMin();
329 const CVector2f
&wmax
= groupMap
.getVisibleWorldMax();
330 if (worldPos
.x
< wmin
.x
|| worldPos
.x
> wmax
.x
||
331 worldPos
.y
< wmin
.y
|| worldPos
.y
> wmax
.y
)
333 // OUT OF VISIBLE REGION CASE
334 _Over
->setActive(true);
335 _Over
->setColorRGBA(selected
? CV_MapEntitySelectColor
.get() : CV_MapEntityHighlightColor
.get());
336 // out of the visible portion, so draw an arrow instead
337 _Over
->setTexture(CV_MapEntityFarTexture
.get());
338 // snap position to inner visible world rect
339 CVector2f m
= 0.5f
* (wmin
+ wmax
);
340 CVector2f dir
= worldPos
- m
;
346 d0
= (wmax
.x
- m
.x
) / dir
.x
;
349 d1
= (wmax
.y
- m
.y
) / dir
.y
;
350 inter
= m
+ std::min(d0
, d1
) * dir
;
352 else if (dir
.y
< 0.f
)
354 d1
= (wmin
.y
- m
.y
) / dir
.y
;
355 inter
= m
+ std::min(d0
, d1
) * dir
;
359 inter
.set(wmax
.x
, m
.y
);
362 else if (dir
.x
< 0.f
)
364 d0
= (wmin
.x
- m
.x
) / dir
.x
;
367 d1
= (wmax
.y
- m
.y
) / dir
.y
;
368 inter
= m
+ std::min(d0
, d1
) * dir
;
370 else if (dir
.y
< 0.f
)
372 d1
= (wmin
.y
- m
.y
) / dir
.y
;
373 inter
= m
+ std::min(d0
, d1
) * dir
;
377 inter
.set(wmin
.x
, m
.y
);
384 inter
.set(m
.x
, wmax
.y
);
386 else if (dir
.y
< 0.f
)
388 inter
.set(m
.x
, wmin
.y
);
395 float size
= CV_MapEntityFarArrowSize
.get();
401 groupMap
.worldToWindow(winInter
, inter
);
403 _Over
->setRenderLayer(3);
404 _Over
->setQuad(winInter
- (size
+ bias
) * dir
, winInter
- bias
* dir
, 0.5f
* size
);
408 sint32 screenInterX
, screenInterY
;
409 groupMap
.windowToScreen(screenInterX
, screenInterY
, (sint32
) winInter
.x
, (sint32
) winInter
.y
);
410 sint32 refCornerX
, refCornerY
;
411 _GlowStar
[0]->getParent()->getCorner(refCornerX
, refCornerY
, Hotspot_BL
);
412 _GlowStarPos
.set((float) (screenInterX
- refCornerX
), (float) (screenInterY
- refCornerY
), 0.f
);
413 _GlowStarActive
= true;
419 _GlowStar
[0]->setActive(false);
420 _GlowStar
[1]->setActive(false);
421 if (closeView
|| hasFocus
)
423 _Over
->setActive(true);
426 _Over
->setColorRGBA(CV_MapEntitySelectColor
.get());
430 _Over
->setColorRGBA(selected
? CV_MapEntitySelectColor
.get() : CV_MapEntityHighlightColor
.get());
432 const std::string
&tex
= closeView
? CV_MapEntitySelectTexture
.get() : CV_MapEntitySmallHighlightTexture
.get();
433 _Over
->setTexture(tex
);
434 _Over
->setRenderLayer(2);
435 _Over
->setQuad(tex
, CVector((float) x
, (float) y
, 0.f
));
439 _Over
->setActive(false);
446 _Over
->setActive(false);
447 _GlowStar
[0]->setActive(false);
448 _GlowStar
[1]->setActive(false);
450 // update 'quad that signal invalid pos'
451 if (_OverInvalid
->getActive())
453 const std::string
&tex
= closeView
? CV_MapEntityInvalidTexture
.get() : CV_MapEntityInvalidTextureSmall
.get();
454 _OverInvalid
->setTexture(tex
);
455 _OverInvalid
->setQuad(tex
, CVector((float) x
, (float) y
, 0.f
));
460 // *********************************************************************************************************
461 void CInstanceMapDeco::setTextureAndFit(const std::string
&bitmapName
)
463 //H_AUTO(R2_CInstanceMapDeco_setTextureAndFit)
466 _Main
->setTexture(bitmapName
);
467 if (!_Main
->isTextureValid())
469 _Main
->setTexture(CV_MapEntityDefaultTexture
.get());
479 // *********************************************************************************************************
480 void CInstanceMapDeco::setActive(bool active
)
482 //H_AUTO(R2_CInstanceMapDeco_setActive)
483 if (active
== _Active
) return;
484 if (_Main
) _Main
->setActive(active
);
485 if (_Over
) _Over
->setActive(active
);
486 if (_GlowStar
[0]) _GlowStar
[0]->setActive(active
);
487 if (_GlowStar
[1]) _GlowStar
[1]->setActive(active
);
488 if (_Orient
) _Orient
->setActive(active
);
492 // *********************************************************************************************************
493 void CInstanceMapDeco::setInvalidPosFlag(bool invalid
)
495 //H_AUTO(R2_CInstanceMapDeco_setInvalidPosFlag)
496 _InvalidPos
= invalid
;
499 _OverInvalid
->setActive(_Active
&& _InvalidPos
);