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>
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/>.
21 #include "displayer_visual.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"
43 using namespace NLMISC
;
45 extern uint SkipFrame
;
51 // ***************************************************************
52 CDisplayerVisual::CDisplayerVisual() : _DisplayFlags(FlagNone
)
58 _IconInSceneCreationFailed
= false;
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;
70 // ***************************************************************
71 CDisplayerVisual::~CDisplayerVisual()
75 CWidgetManager::getInstance()->unMakeWindow(_IconInScene
);
76 if (_IconInScene
->getParent())
78 _IconInScene
->getParent()->delGroup(_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();
113 CInstance
*parentInstance
= inst
->getParent();
116 result
= parentInstance
->getDisplayerVisual();
118 _LastParent
= result
;
119 _LastParentOk
= true;
123 // ***************************************************************
124 const CDisplayerVisual
*CDisplayerVisual::getParent() const
126 //H_AUTO(R2_CDisplayerVisual_getParent)
127 return (const_cast<CDisplayerVisual
*>(this))->getParent();
128 /*CInstance *inst = getDisplayedInstance();
130 CInstance *parentInstance = inst->getParent();
133 return parentInstance->getDisplayerVisual();
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);
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")
196 /*else if (attrName == "DisplayMode")
199 uint numSons = getNumSons();
200 for(uint k = 0; k < numSons; ++k)
202 CDisplayerVisual *dv = getSon(k);
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;
230 nlwarning("Trying to set an invalid display mode : %d", (int) _DisplayMode);
234 // *********************************************************************************************************
235 void CDisplayerVisual::updatePos()
237 //H_AUTO(R2_CDisplayerVisual_updatePos)
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));
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
;
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
297 // If I'm outside of current map then don't display the flag
298 CScenarioEntryPoints::CCompleteIsland
*islandDesc
= getEditor().getIslandCollision().getCurrIslandDesc();
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);
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;
339 updateWorldPos(); // do not recurse here because sons pos have not been initialized yet
340 //updateDisplayMode();
341 if (isActiveInCurrentAct())
350 // *********************************************************************************************************
351 void CDisplayerVisual::onErase()
353 //H_AUTO(R2_CDisplayerVisual_onErase)
360 // *********************************************************************************************************
361 void CDisplayerVisual::onPreActChanged()
363 //H_AUTO(R2_CDisplayerVisual_onPreActChanged)
365 if (!isActiveInCurrentAct())
374 // *********************************************************************************************************
375 void CDisplayerVisual::onActChanged()
377 //H_AUTO(R2_CDisplayerVisual_onActChanged)
379 if (isActiveInCurrentAct())
388 // *********************************************************************************************************
389 void CDisplayerVisual::onContinentChanged()
391 //H_AUTO(R2_CDisplayerVisual_onContinentChanged)
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())
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()))
426 _IconInScene
->setActive(false);
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);
441 _IconInScene
= dynamic_cast<CGroupInScene
*>(group
);
444 nlwarning("Template %s has bad type : should be a derived group from CGroupInScene", iconTemplateName
);
446 _IconInSceneCreationFailed
= true;
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
);
455 pRoot
->addGroup (group
);
460 _IconInSceneCreationFailed
= true;
465 _IconInScene
->setActive(true);
466 // tmp set a position above head
467 evalIconInScenePos(_IconInScene
->Position
);
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
);
498 // *********************************************************************************************************
499 bool CDisplayerVisual::evalEnterPoint(const NLMISC::CVector
&/* startPoint */, NLMISC::CVector
&result
)
501 //H_AUTO(R2_CDisplayerVisual_evalEnterPoint)
502 result
= evalLinkPoint(false);
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)
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();
558 _LastCamDist
= -100.f
;
559 //nlwarning("Waiting skip frame : %d", (int) SkipFrame);
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;
581 return CDisplayerVisual::DisplayModeVisible
;
585 const CDisplayerVisual
*parent
= getParent();
586 if (_InheritDisplayMode
&& parent
)
588 TDisplayMode parentDM
= parent
->getActualDisplayMode();
589 dm
= parentDM
== DisplayModeVisible
? _DisplayMode
: parentDM
;
596 static volatile bool bypass2
= false;
599 return CDisplayerVisual::DisplayModeVisible
;
602 if (!getDisplayedInstance()->getSelectableFromRoot() && dm
!= DisplayModeHidden
)
604 dm
= DisplayModeFrozen
;
607 static volatile bool bypass3
= false;
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
;
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
¶meters
)
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
);
670 _DisplayMode
= (TDisplayMode
) mode
;
671 uint numSons
= getNumSons();
672 for(uint k
= 0; k
< numSons
; ++k
)
674 CDisplayerVisual
*dv
= getSon(k
);
677 dv
->onParentDisplayModeChanged();