Add infos into target window
[ryzomcore.git] / ryzom / client / src / r2 / displayer_visual.cpp
blob6d3c1a32edbd93bb3d7f00f7362d8935a39f7797
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 //
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/>.
20 #include "stdpch.h"
21 #include "displayer_visual.h"
22 // r2
23 #include "instance.h"
24 #include "editor.h"
25 #include "tool_select_move.h"
27 #include "nel/misc/algo.h"
28 #include "nel/misc/vector_2f.h"
30 #include "../time_client.h"
31 #include "nel/gui/lua_ihm.h"
32 #include "../global.h"
34 #include "../interface_v3/interface_manager.h"
35 #include "../interface_v3/group_in_scene.h"
37 #include "r2_config.h"
39 #ifdef DEBUG_NEW
40 #define new DEBUG_NEW
41 #endif
43 using namespace NLMISC;
45 extern uint SkipFrame;
47 namespace R2
51 // ***************************************************************
52 CDisplayerVisual::CDisplayerVisual() : _DisplayFlags(FlagNone)
54 _BlinkStartDate = 0;
55 _Pos.set(0, 0, 0);
56 _WorldPos = _Pos;
57 _IconInScene = NULL;
58 _IconInSceneCreationFailed = false;
59 _DisplayFlags = 0;
60 _RotateInProgress = false;
61 _MoveInProgress = false;
62 // TODO nico : optim here : only one decal used at a time
63 _LastCamDist = -100.f;
64 _DisplayMode = DisplayModeVisible;
65 _InheritDisplayMode = false; // filled at init by this displayer lua parameter
66 _LastParentOk = false;
67 _LastParent = NULL;
70 // ***************************************************************
71 CDisplayerVisual::~CDisplayerVisual()
73 if (_IconInScene)
75 CWidgetManager::getInstance()->unMakeWindow(_IconInScene);
76 if (_IconInScene->getParent())
78 _IconInScene->getParent()->delGroup(_IconInScene);
80 else
82 delete _IconInScene;
87 // ***************************************************************
88 void CDisplayerVisual::setDisplayFlag(TDisplayFlags flag, bool on)
90 //H_AUTO(R2_CDisplayerVisual_setDisplayFlag)
91 nlctassert(FlagCount <= 32);
92 nlassert((uint) flag < FlagCount);
93 setFlags(_DisplayFlags, 1 << flag, on);
96 // ***************************************************************
97 bool CDisplayerVisual::getDisplayFlag(TDisplayFlags flag) const
99 //H_AUTO(R2_CDisplayerVisual_getDisplayFlag)
100 nlctassert(FlagCount <= 32);
101 nlassert((uint) flag < FlagCount);
102 return (_DisplayFlags & (1 << flag)) != 0;
105 // ***************************************************************
106 CDisplayerVisual *CDisplayerVisual::getParent()
108 if (_LastParentOk) return _LastParent;
109 CDisplayerVisual *result = NULL;
110 //H_AUTO(R2_CDisplayerVisual_getParent)
111 CInstance *inst = getDisplayedInstance();
112 nlassert(inst);
113 CInstance *parentInstance = inst->getParent();
114 if (parentInstance)
116 result = parentInstance->getDisplayerVisual();
118 _LastParent = result;
119 _LastParentOk = true;
120 return result;
123 // ***************************************************************
124 const CDisplayerVisual *CDisplayerVisual::getParent() const
126 //H_AUTO(R2_CDisplayerVisual_getParent)
127 return (const_cast<CDisplayerVisual *>(this))->getParent();
128 /*CInstance *inst = getDisplayedInstance();
129 nlassert(inst);
130 CInstance *parentInstance = inst->getParent();
131 if (parentInstance)
133 return parentInstance->getDisplayerVisual();
135 return NULL;*/
138 // ***************************************************************
139 void CDisplayerVisual::onFocus(bool focused)
141 //H_AUTO(R2_CDisplayerVisual_onFocus)
142 setDisplayFlag(FlagHasFocus, focused);
145 // ***************************************************************
146 void CDisplayerVisual::onSelect(bool selected)
148 //H_AUTO(R2_CDisplayerVisual_onSelect)
149 setDisplayFlag(FlagSelected, selected);
152 // ***************************************************************
153 void CDisplayerVisual::onPostHrcMove()
155 //H_AUTO(R2_CDisplayerVisual_onPostHrcMove)
156 _LastParentOk = false; // must update parent
157 updateWorldPosRecurse();
161 // ***************************************************************
162 void CDisplayerVisual::blink()
164 //H_AUTO(R2_CDisplayerVisual_blink)
165 _BlinkStartDate = T1;
168 // ***************************************************************
169 int CDisplayerVisual::luaBlink(CLuaState &ls)
171 //H_AUTO(R2_CDisplayerVisual_luaBlink)
172 CLuaIHM::checkArgCount(ls, "luaBlink", 1);
173 blink();
174 return 0;
177 // ***************************************************************
178 NLMISC::CRGBA CDisplayerVisual::getBlinkColor(NLMISC::CRGBA defaultColor, NLMISC::CRGBA blinkColor) const
180 //H_AUTO(R2_NLMISC_CRGBA )
181 const uint NUM_BLINKS = 3;
182 const uint BLINK_LENGTH_IN_MS = 100;
183 sint64 blink = (T1 - _BlinkStartDate) / BLINK_LENGTH_IN_MS;
184 if (blink > NUM_BLINKS) return defaultColor;
185 return !(blink & 1) ? blinkColor : defaultColor;
188 // *********************************************************************************************************
189 void CDisplayerVisual::onAttrModified(const std::string &attrName, sint32 /* attrIndex */)
191 //H_AUTO(R2_CDisplayerVisual_onAttrModified)
192 if (attrName == "Position")
194 updatePos();
196 /*else if (attrName == "DisplayMode")
198 updateDisplayMode();
199 uint numSons = getNumSons();
200 for(uint k = 0; k < numSons; ++k)
202 CDisplayerVisual *dv = getSon(k);
203 if (dv)
205 dv->onParentDisplayModeChanged();
212 // *********************************************************************************************************
213 /*void CDisplayerVisual::updateDisplayMode()
215 sint value = (sint) getNumber(&getProps(), "DisplayMode");
216 if (value >= 0 && value < DisplayModeCount)
218 TDisplayMode newDisplayMode = (TDisplayMode) value;
219 if (newDisplayMode != _DisplayMode)
221 //if (newDisplayMode == DisplayModeFrozen && getEditor().getSelectedInstance() == getDisplayedInstance())
223 // getEditor().setSelectedInstance(NULL);
225 //_DisplayMode = newDisplayMode;
228 else
230 nlwarning("Trying to set an invalid display mode : %d", (int) _DisplayMode);
234 // *********************************************************************************************************
235 void CDisplayerVisual::updatePos()
237 //H_AUTO(R2_CDisplayerVisual_updatePos)
238 updateLocalPos();
239 updateWorldPosRecurse();
242 // *********************************************************************************************************
243 void CDisplayerVisual::updateLocalPos()
245 //H_AUTO(R2_CDisplayerVisual_updateLocalPos)
246 if (getProps().findAttr("Position"))
248 _Pos = getVector(getObject(&getProps(), "Position"));
249 static volatile bool wantAssert = true;
250 if (!isValidDouble(_Pos.x) || !isValidDouble(_Pos.y) ||!isValidDouble(_Pos.z))
252 // nlassert(!wantAssert);
253 BOMB_IF(wantAssert,"'wantAssert' was triggered",_Pos.set(0, 0, 0));
256 else
258 _Pos.set(0, 0, 0);
262 // *********************************************************************************************************
263 bool CDisplayerVisual::inheritPos() const
265 //H_AUTO(R2_CDisplayerVisual_inheritPos)
266 return getNumber(&getProps(), "InheritPos") != 0;
269 // *********************************************************************************************************
270 void CDisplayerVisual::updateWorldPos()
272 //H_AUTO(R2_CDisplayerVisual_updateWorldPos)
273 CDisplayerVisual *parent = getParent();
274 if (parent && inheritPos())
276 _WorldPos = parent->getWorldPos() + _Pos;
278 else
280 _WorldPos = _Pos;
282 static volatile bool wantAssert = true;
283 if (!isValidDouble(_WorldPos.x) || !isValidDouble(_WorldPos.y) ||!isValidDouble(_WorldPos.z))
285 nlassert(!wantAssert);
287 updateValidPosFlag();
290 // *********************************************************************************************************
291 void CDisplayerVisual::updateValidPosFlag()
293 //H_AUTO(R2_CDisplayerVisual_updateValidPosFlag)
294 // if I'm not a compound object, update my 'BadPos' flag
295 if (!isCompound())
297 // If I'm outside of current map then don't display the flag
298 CScenarioEntryPoints::CCompleteIsland *islandDesc = getEditor().getIslandCollision().getCurrIslandDesc();
299 if (islandDesc)
301 if ((sint32) _WorldPos.x < islandDesc->XMin ||
302 (sint32) _WorldPos.x > islandDesc->XMax ||
303 (sint32) _WorldPos.y < islandDesc->YMin ||
304 (sint32) _WorldPos.y > islandDesc->YMax)
306 setDisplayFlag(FlagBadPos, false);
307 return;
310 setDisplayFlag(FlagBadPos, !getEditor().getIslandCollision().isValidPos(NLMISC::CVector(_WorldPos)));
314 // *********************************************************************************************************
315 void CDisplayerVisual::updateWorldPosRecurse()
317 //H_AUTO(R2_CDisplayerVisual_updateWorldPosRecurse)
318 struct CWorldPosUpdater : public IInstanceVisitor
320 virtual void visit(CInstance &inst)
322 if (inst.getDisplayerVisual())
324 inst.getDisplayerVisual()->updateWorldPos();
328 nlassert(getDisplayedInstance());
329 CWorldPosUpdater worldPosUpdater;
330 getDisplayedInstance()->visit(worldPosUpdater);
333 // *********************************************************************************************************
334 void CDisplayerVisual::onPostCreate()
336 //H_AUTO(R2_CDisplayerVisual_onPostCreate)
337 _LastParentOk = false;
338 updateLocalPos();
339 updateWorldPos(); // do not recurse here because sons pos have not been initialized yet
340 //updateDisplayMode();
341 if (isActiveInCurrentAct())
343 if (!getActive())
345 setActive(true);
350 // *********************************************************************************************************
351 void CDisplayerVisual::onErase()
353 //H_AUTO(R2_CDisplayerVisual_onErase)
354 if (getActive())
356 setActive(false);
360 // *********************************************************************************************************
361 void CDisplayerVisual::onPreActChanged()
363 //H_AUTO(R2_CDisplayerVisual_onPreActChanged)
364 updatePos();
365 if (!isActiveInCurrentAct())
367 if (getActive())
369 setActive(false);
374 // *********************************************************************************************************
375 void CDisplayerVisual::onActChanged()
377 //H_AUTO(R2_CDisplayerVisual_onActChanged)
378 updatePos();
379 if (isActiveInCurrentAct())
381 if (!getActive())
383 setActive(true);
388 // *********************************************************************************************************
389 void CDisplayerVisual::onContinentChanged()
391 //H_AUTO(R2_CDisplayerVisual_onContinentChanged)
392 if (getActive())
394 setActive(false);
395 setActive(true); // force a refresh of collision (EntitiesManager::changeContinent updates the primitive, but broken for an unknown reason ...)
400 // *********************************************************************************************************
401 bool CDisplayerVisual::isActiveInCurrentAct() const
403 //H_AUTO(R2_CDisplayerVisual_isActiveInCurrentAct)
404 // parent act should be the base act (always exists), or the selected act
405 CInstance *parentAct = getDisplayedInstance()->getParentAct();
406 if (parentAct == getEditor().getBaseAct() || parentAct == getEditor().getCurrentAct())
408 return true;
410 return false;
413 // *********************************************************************************************************
414 void CDisplayerVisual::onPostRender()
416 //H_AUTO(R2_CDisplayerVisual_onPostRender)
417 if (!getActive()) return;
419 // if this entity is currently moving then don't display the 'stop' icon
420 // (it is already drawn by the mouse cursor)
421 if (getDisplayedInstance() == getEditor().getSelectedInstance()
422 && dynamic_cast<CToolSelectMove *>(getEditor().getCurrentTool()))
424 if (_IconInScene)
426 _IconInScene->setActive(false);
429 else
431 if (getDisplayFlag(FlagBadPos))
433 if (!_IconInScene && !_IconInSceneCreationFailed)
435 CInterfaceManager *pIM = CInterfaceManager::getInstance();
436 const char *iconTemplateName = "r2ed_bad_pos_icon";
437 // if the in scene 'stop' window wasn't created, then create it now
438 CInterfaceGroup *group = CWidgetManager::getInstance()->getParser()->createGroupInstance (iconTemplateName , "ui:interface", NULL, 0);
439 if (group)
441 _IconInScene = dynamic_cast<CGroupInScene *>(group);
442 if (!_IconInScene)
444 nlwarning("Template %s has bad type : should be a derived group from CGroupInScene", iconTemplateName);
445 delete group;
446 _IconInSceneCreationFailed = true;
448 else
450 // Link to the interface
451 CWidgetManager::getInstance()->addWindowToMasterGroup("ui:interface", group);
452 CInterfaceGroup *pRoot = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface"));
453 group->setParent(pRoot);
454 if (pRoot)
455 pRoot->addGroup (group);
458 else
460 _IconInSceneCreationFailed = true;
463 if (_IconInScene)
465 _IconInScene->setActive(true);
466 // tmp set a position above head
467 evalIconInScenePos(_IconInScene->Position);
470 else
472 if (_IconInScene)
474 _IconInScene->setActive(false);
480 // *********************************************************************************************************
481 void CDisplayerVisual::evalIconInScenePos(NLMISC::CVector &dest) const
483 //H_AUTO(R2_CDisplayerVisual_evalIconInScenePos)
484 NLMISC::CAABBox selectBox = getSelectBox();
485 float radius = std::max(selectBox.getHalfSize().x, selectBox.getHalfSize().y);
486 // use middle front of bbox for icon pos
487 NLMISC::CVector result = getWorldPos().asVector() - radius * MainCam.getMatrix().getJ() + selectBox.getHalfSize().z * CVector::K;
488 static volatile bool wantAssert = true;
489 if (!isValidDouble(result.x) || !isValidDouble(result.y) ||!isValidDouble(result.z))
491 nlassert(!wantAssert);
492 return;
494 dest = result;
498 // *********************************************************************************************************
499 bool CDisplayerVisual::evalEnterPoint(const NLMISC::CVector &/* startPoint */, NLMISC::CVector &result)
501 //H_AUTO(R2_CDisplayerVisual_evalEnterPoint)
502 result = evalLinkPoint(false);
503 return true;
506 // *********************************************************************************************************
507 NLMISC::CVector CDisplayerVisual::evalExitPoint()
509 //H_AUTO(R2_NLMISC_CVector )
510 return evalLinkPoint(false);
513 // *********************************************************************************************************
514 void CDisplayerVisual::getSonsWorldPos2f(std::vector<NLMISC::CVector2f> &result)
516 //H_AUTO(R2_CDisplayerVisual_getSonsWorldPos2f)
517 result.clear();
520 // *********************************************************************************************************
521 void CDisplayerVisual::getSons(std::vector<CDisplayerVisual *> &sons) const
523 //H_AUTO(R2_CDisplayerVisual_getSons)
524 sons.clear(); // no sons by default
527 // *********************************************************************************************************
528 void CDisplayerVisual::setRotateInProgress(bool rotateInProgress)
530 //H_AUTO(R2_CDisplayerVisual_setRotateInProgress)
531 _RotateInProgress = rotateInProgress;
534 // *********************************************************************************************************
535 void CDisplayerVisual::setMoveInProgress(bool moveInProgress)
537 //H_AUTO(R2_CDisplayerVisual_setMoveInProgress)
538 _MoveInProgress = moveInProgress;
541 // *********************************************************************************************************
542 bool CDisplayerVisual::testNeedZEval()
544 //H_AUTO(R2_CDisplayerVisual_testNeedZEval)
546 if (SkipFrame == 0) // don't update just after a tp because landscape hasn't been updated yet ...
548 float newCamDist = (MainCam.getMatrix().getPos() - _WorldPos).norm();
549 if (fabsf(newCamDist - _LastCamDist) >= 5.f)
551 _LastCamDist = newCamDist;
552 updateValidPosFlag();
553 return true;
556 else
558 _LastCamDist = -100.f;
559 //nlwarning("Waiting skip frame : %d", (int) SkipFrame);
561 return false;
564 // *********************************************************************************************************
565 bool CDisplayerVisual::isSelectable() const
567 //H_AUTO(R2_CDisplayerVisual_isSelectable)
568 static volatile bool bypass = false;
569 if (bypass) return false;
570 TDisplayMode dm = getActualDisplayMode();
571 return getDisplayedInstance()->getSelectableFromRoot() && (dm == DisplayModeVisible || dm == DisplayModeLocked);
574 // *********************************************************************************************************
575 CDisplayerVisual::TDisplayMode CDisplayerVisual::getActualDisplayMode() const
577 //H_AUTO(R2_CDisplayerVisual_getActualDisplayMode)
578 static volatile bool bypass = false;
579 if (bypass)
581 return CDisplayerVisual::DisplayModeVisible;
584 TDisplayMode dm;
585 const CDisplayerVisual *parent = getParent();
586 if (_InheritDisplayMode && parent)
588 TDisplayMode parentDM = parent->getActualDisplayMode();
589 dm = parentDM == DisplayModeVisible ? _DisplayMode : parentDM;
591 else
593 dm= _DisplayMode;
596 static volatile bool bypass2 = false;
597 if (bypass2)
599 return CDisplayerVisual::DisplayModeVisible;
602 if (!getDisplayedInstance()->getSelectableFromRoot() && dm != DisplayModeHidden)
604 dm = DisplayModeFrozen;
607 static volatile bool bypass3 = false;
608 if (bypass3)
610 return CDisplayerVisual::DisplayModeVisible;
613 // If it is not an animation but a scenario started from ring access do not display things
614 if ( CEditor::getIsStartingScenario() )
616 return DisplayModeHidden;
618 return dm;
621 // *********************************************************************************************************
622 CRGBA CDisplayerVisual::getDisplayModeColorInScene() const
624 //H_AUTO(R2_CDisplayerVisual_getDisplayModeColorInScene)
625 switch(getActualDisplayMode())
627 case DisplayModeVisible: return CV_UnselectedInstanceColor.get();
628 case DisplayModeFrozen: return CV_FrozenInstanceColor.get();
629 case DisplayModeLocked: return CV_LockedInstanceColor.get();
630 case DisplayModeArray: return CV_ArrayInstanceColor.get();
631 default: return CRGBA(0, 0, 0 ,0);
635 // *********************************************************************************************************
636 CRGBA CDisplayerVisual::getDisplayModeColorInMap() const
638 //H_AUTO(R2_CDisplayerVisual_getDisplayModeColorInMap)
639 switch(getActualDisplayMode())
641 case DisplayModeVisible: return CRGBA::White;
642 case DisplayModeFrozen: return CV_MapEntityFrozenColor.get();
643 case DisplayModeLocked: return CV_MapEntityLockedColor.get();
644 case DisplayModeArray: return CV_ArrayInstanceColor.get();
645 default: return CRGBA(0, 0, 0 ,0);
649 // *********************************************************************************************************
650 bool CDisplayerVisual::init(const CLuaObject &parameters)
652 //H_AUTO(R2_CDisplayerVisual_init)
653 if (parameters["InheritDisplayMode"].isBoolean())
655 _InheritDisplayMode = parameters["InheritDisplayMode"].toBoolean();
657 return CDisplayerBase::init(parameters);
660 // *********************************************************************************************************
661 void CDisplayerVisual::setDisplayMode(sint32 mode)
663 //H_AUTO(R2_CDisplayerVisual_setDisplayMode)
664 if (mode == _DisplayMode) return;
665 if (mode < 0 || mode >= DisplayModeCount)
667 nlwarning("Trying to set invalid display mode : %d", (int) mode);
668 return;
670 _DisplayMode = (TDisplayMode) mode;
671 uint numSons = getNumSons();
672 for(uint k = 0; k < numSons; ++k)
674 CDisplayerVisual *dv = getSon(k);
675 if (dv)
677 dv->onParentDisplayModeChanged();
683 } // R2