Add infos into target window
[ryzomcore.git] / ryzom / client / src / r2 / instance_map_deco.cpp
blob46b1ad874b36ff2da959cf5b746f33db004674e5
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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>
7 //
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/>.
21 #include "stdpch.h"
23 #include "instance_map_deco.h"
24 #include "r2_config.h"
25 #include "tool.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;
36 #ifdef DEBUG_NEW
37 #define new DEBUG_NEW
38 #endif
40 namespace R2
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"))
49 help.clear();
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)
63 _Main = NULL;
64 _Over = NULL;
65 _OverInvalid = NULL;
66 _Orient = NULL;
67 _GlowStar[0] = _GlowStar[1] = NULL;
68 _GlowStarActive = false;
69 _OrientBlendFactor = 0.f;
70 _LastCloseView = false;
71 _Instance = NULL;
72 _AddedToMap = false;
73 _Orientable = false;
74 _Active = true;
75 _InvalidPos = false;
78 // *********************************************************************************************************
79 void CInstanceMapDeco::setDisplayedInstance(CInstance *instance, bool orientable)
81 //H_AUTO(R2_CInstanceMapDeco_setDisplayedInstance)
82 nlassert(instance);
83 nlassert(!_Instance); // should be called once only
84 _Instance = instance;
85 _Orientable = orientable;
88 // *********************************************************************************************************
89 CVector2f CInstanceMapDeco::getWorldPos() const
91 //H_AUTO(R2_CInstanceMapDeco_getWorldPos)
92 nlassert(_Instance);
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)
102 nlassert(_Instance);
103 nlassert(_Main);
104 nlassert(_Over);
105 nlassert(_OverInvalid);
106 _Main->invalidateCoords();
107 _Over->invalidateCoords();
108 _OverInvalid->invalidateCoords();
109 if (_GlowStar[0])
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)
121 nlassert(_Instance);
122 CViewBase::TCtorParam param;
123 CCtrlQuad *q = new CCtrlQuad( param );
124 q->setActive(false);
125 q->setModulateGlobalColor(false);
126 owner.addCtrl(q);
127 q->setParent(&owner);
128 return q;
132 // *********************************************************************************************************
133 void CInstanceMapDeco::onAdd(CGroupMap &owner)
135 //H_AUTO(R2_CInstanceMapDeco_onAdd)
136 nlassert(_Instance);
137 nlassert(!_Main);
138 nlassert(!_Over);
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);
158 if (_Orientable)
160 _Orient = newQuad(owner);
161 _Orient->setTexture(CV_MapEntityOrientTexture.get());
162 _Orient->setRenderLayer(3);
163 _Orient->setActive(_Active);
166 CInterfaceGroup *window = owner.getParentContainer();
167 if (window)
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());
182 _AddedToMap = true;
185 // *********************************************************************************************************
186 void CInstanceMapDeco::onRemove(CGroupMap &owner)
188 //H_AUTO(R2_CInstanceMapDeco_onRemove)
189 nlassert(_Instance);
190 nlassert(_Main);
191 nlassert(_Over);
192 nlassert(_OverInvalid);
193 owner.delCtrl(_Main);
194 _Main = NULL;
195 owner.delCtrl(_Over);
196 _Over = NULL;
197 owner.delCtrl(_OverInvalid);
198 _OverInvalid = NULL;
199 if (_Orient)
201 owner.delCtrl(_Orient);
202 _Orient = NULL;
204 if (_GlowStar[0])
206 _GlowStar[0]->getParent()->delCtrl(_GlowStar[0]);
207 _GlowStar[0] = NULL;
208 _GlowStar[1]->getParent()->delCtrl(_GlowStar[1]);
209 _GlowStar[1] = NULL;
211 _AddedToMap = false;
212 _Instance = NULL;
216 // *********************************************************************************************************
217 void CInstanceMapDeco::onPreRender(CGroupMap &groupMap)
219 //H_AUTO(R2_CInstanceMapDeco_onPreRender)
220 if (!_Active) return;
221 nlassert(_Instance);
222 if (_GlowStarActive)
224 if (_GlowStar[0])
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();
236 if (_Orient)
238 bool closeView = groupMap.getMeterPerPixel() < CV_MapEntityCloseDist.get();
239 CDisplayerVisual *vd = _Instance->getDisplayerVisual();
240 if (vd)
242 if (_LastCloseView!= closeView)
244 _OrientBlendFactor = closeView ? 0.5f : 0.f;
246 if (vd->getRotateInProgress())
248 _OrientBlendFactor = 1.f;
250 else
252 // fade to default alpha
253 NLMISC::incrementalBlend(_OrientBlendFactor, closeView ? 0.5f : 0.f, DT * 1000.f / favoid0(CV_MapEntityOrientBlendTimeInMs.get()));
256 else
258 _OrientBlendFactor = 0.f;
262 if (_OrientBlendFactor == 0.f)
264 _Orient->setActive(false);
266 else
268 _Orient->setActive(true);
269 _Orient->setColorRGBA(CRGBA(255, 255, 255, (uint8) (255 * _OrientBlendFactor)));
270 sint32 x;
271 sint32 y;
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;
289 nlassert(_Instance);
290 _GlowStarActive = false;
291 if (!_Main || !_Over || !_OverInvalid) return;
292 sint32 x;
293 sint32 y;
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();
298 if (currIsland)
300 if (!currIsland->isIn(worldPos))
302 setActive(false);
303 return;
306 groupMap.worldToWindowSnapped(x, y, getWorldPos());
307 _Main->setX(x);
308 _Main->setY(y);
309 CDisplayerVisual *vd = _Instance->getDisplayerVisual();
310 if (!vd)
312 _Over->setActive(false);
313 _OverInvalid->setActive(false);
314 return;
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;
341 CVector2f inter;
342 float d0;
343 float d1;
344 if (dir.x > 0.f)
346 d0 = (wmax.x - m.x) / dir.x;
347 if (dir.y > 0.f)
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;
357 else
359 inter.set(wmax.x, m.y);
362 else if (dir.x < 0.f)
364 d0 = (wmin.x - m.x) / dir.x;
365 if (dir.y > 0.f)
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;
375 else
377 inter.set(wmin.x, m.y);
380 else
382 if (dir.y > 0.f)
384 inter.set(m.x, wmax.y);
386 else if (dir.y < 0.f)
388 inter.set(m.x, wmin.y);
390 else
392 inter = m;
395 float size = CV_MapEntityFarArrowSize.get();
396 // TMP TMP
397 // size = size;
398 float bias = 1.f;
399 dir.normalize();
400 CVector2f winInter;
401 groupMap.worldToWindow(winInter, inter);
403 _Over->setRenderLayer(3);
404 _Over->setQuad(winInter - (size + bias) * dir, winInter - bias * dir, 0.5f * size);
406 if (_GlowStar[0])
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;
416 else
418 // VISIBLE CASE
419 _GlowStar[0]->setActive(false);
420 _GlowStar[1]->setActive(false);
421 if (closeView || hasFocus)
423 _Over->setActive(true);
424 if (!closeView)
426 _Over->setColorRGBA(CV_MapEntitySelectColor.get());
428 else
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));
437 else
439 _Over->setActive(false);
443 else
445 // no focus
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)
464 nlassert(_Instance);
465 nlassert(_Main);
466 _Main->setTexture(bitmapName);
467 if (!_Main->isTextureValid())
469 _Main->setTexture(CV_MapEntityDefaultTexture.get());
470 _Main->setX(14);
471 _Main->setY(14);
473 else
475 _Main->fitTexture();
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);
489 _Active = active;
492 // *********************************************************************************************************
493 void CInstanceMapDeco::setInvalidPosFlag(bool invalid)
495 //H_AUTO(R2_CInstanceMapDeco_setInvalidPosFlag)
496 _InvalidPos = invalid;
497 if (_OverInvalid)
499 _OverInvalid->setActive(_Active && _InvalidPos);
505 } // R2