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 "nel/misc/line.h"
24 #include "nel/3d/u_bone.h"
26 #include "nel/3d/u_landscape.h"
28 #include "nel/3d/zone.h"
30 #include "displayer_visual_group.h"
31 #include "r2_config.h"
34 #include "tool_draw_prim.h"
36 #include "../entity_cl.h"
37 #include "../global.h"
39 #include "../landscape_poly_drawer.h"
40 #include "nel/gui/ctrl_polygon.h"
41 #include "nel/gui/ctrl_quad.h"
42 #include "../time_client.h"
53 using namespace NLMISC
;
56 extern ULandscape
*Landscape
;
61 // create a special selectable polygon
62 class CCtrlPolygonSelectable
: public CCtrlPolygon
, public IDisplayerUIHandle
65 CCtrlPolygonSelectable( CViewBase::TCtorParam
¶m
, CInstance
&instance
) : CCtrlPolygon(param
), Instance(instance
) {}
66 // from IDisplayerUIHandle
67 virtual CInstance
&getDisplayedInstance() { return Instance
; }
68 // from IDisplayerUIHandle
69 virtual bool contains(sint32 mouseXInWindow
, sint32 mouseYInWindow
) const
71 if (!_Parent
) return false;
73 // relies on parent class CViewPolygon::contains
74 return CCtrlPolygon::contains(CVector2f(mouseXInWindow
+ 0.5f
, mouseYInWindow
+ 0.5f
));
77 virtual void getContextHelp(std::string
&help
) const
79 help
= Instance
.getDisplayName().toUtf8();
80 if (help
== NLMISC::CI18N::get("uiR2EDNoName"))
83 bool emptyContextHelp() const { return true; }
84 bool wantInstantContextHelp() const { return true; }
86 virtual bool preciseHitTest(sint32 x
, sint32 y
) const
88 if (!_Parent
) return false;
90 _Parent
->getCorner(winX
, winY
, _ParentPosRef
);
91 return contains(x
- winX
, y
- winY
);
96 // TMP TMP until matrix precision is solved
98 void computeScaledVertex(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
)
100 CGroupMap
*gm
= CTool::getWorldMap();
101 if (!gm
) dest
= CVector::Null
;
102 else gm
->worldToWindow(dest
, src
);
106 // create a special selectable polygon
107 class CCtrlQuadSelectable
: public CCtrlQuad
, public IDisplayerUIHandle
110 CCtrlQuadSelectable( CViewBase::TCtorParam
¶m
, CInstance
&instance
, uint edgeIndex
) : CCtrlQuad(param
), Instance(instance
), EdgeIndex(edgeIndex
) {}
111 // from IDisplayerUIHandle
112 virtual CInstance
&getDisplayedInstance() { return Instance
; }
113 // from IDisplayerUIHandle
114 virtual bool isEdge() const { return true; }
115 // from IDisplayerUIHandle
116 virtual uint
getEdgeIndex() const { return EdgeIndex
; }
117 // from IDisplayerUIHandle
118 virtual bool contains(sint32 mouseXInWindow
, sint32 mouseYInWindow
) const
120 if (!_Parent
) return false;
122 // relies on parent class CViewPolygon::contains
123 return CCtrlQuad::contains(CVector2f(mouseXInWindow
+ 0.5f
, mouseYInWindow
+ 0.5f
));
126 virtual void getContextHelp(std::string
&help
) const
128 help
= Instance
.getDisplayName().toUtf8();
129 if (help
== NLMISC::CI18N::get("uiR2EDNoName"))
132 bool emptyContextHelp() const { return true; }
133 bool wantInstantContextHelp() const { return true; }
135 virtual bool preciseHitTest(sint32 x
, sint32 y
) const
137 if (!_Parent
) return false;
139 _Parent
->getCorner(winX
, winY
, _ParentPosRef
);
140 return contains(x
- winX
, y
- winY
);
142 virtual bool handleEvent (const NLGUI::CEventDescriptor
&/* event */)
153 // *********************************************************************************************************
154 CDisplayerVisualGroup::CDisplayerVisualGroup()
156 _ArrayName
= "Components";
157 _DrawnThisFrame
= false;
159 _CurrPrimValid
= true;
162 _CurrPrimInaccessible
= false;
163 _ContextualVisibilityActive
= false;
164 _ContextualVisibilityDate
= -1;
165 _VisibleLastFrame
= false;
168 // *********************************************************************************************************
169 void CDisplayerVisualGroup::touch()
171 //H_AUTO(R2_CDisplayerVisualGroup_touch)
173 _InstanceListTouched
= true;
174 _AccessibilityTouched
= true;
177 // *********************************************************************************************************
178 void CDisplayerVisualGroup::setDisplayedInstance(CInstance
*instance
)
180 //H_AUTO(R2_CDisplayerVisualGroup_setDisplayedInstance)
181 CDisplayerVisual::setDisplayedInstance(instance
);
182 _Prim
.DisplayedInstance
= instance
;
185 // *********************************************************************************************************
186 CCtrlPolygon
*CDisplayerVisualGroup::CSelectablePrimRender::newCtrlPolygon() const
188 //H_AUTO(R2_CDisplayerVisualGroup_CSelectablePrimRender)
189 nlassert(DisplayedInstance
);
190 CViewBase::TCtorParam param
;
191 CCtrlPolygonSelectable
*result
= new CCtrlPolygonSelectable( param
, *DisplayedInstance
);
192 result
->setId(DisplayedInstance
->getId());
193 result
->setToolTipParent(CCtrlBase::TTMouse
);
194 result
->setToolTipParentPosRef(Hotspot_BR
);
195 result
->setToolTipPosRef(Hotspot_TL
);
199 // *********************************************************************************************************
200 CCtrlQuad
*CDisplayerVisualGroup::CSelectablePrimRender::newCtrlQuad(uint edgeIndex
) const
202 //H_AUTO(R2_CDisplayerVisualGroup_CSelectablePrimRender)
203 nlassert(DisplayedInstance
);
204 CViewBase::TCtorParam param
;
205 CCtrlQuadSelectable
*result
= new CCtrlQuadSelectable( param
, *DisplayedInstance
, edgeIndex
);
206 result
->setToolTipParent(CCtrlBase::TTMouse
);
207 result
->setToolTipParentPosRef(Hotspot_BR
);
208 result
->setToolTipPosRef(Hotspot_TL
);
212 // *********************************************************************************************************
213 bool CDisplayerVisualGroup::init(const CLuaObject
¶meters
)
215 //H_AUTO(R2_CDisplayerVisualGroup_init)
216 CDisplayerVisual::init(parameters
);
217 if (parameters
["Look"].isTable())
219 _PrimLook
.init(parameters
["Look"]);
221 if (parameters
["InvalidLook"].isTable())
223 _PrimLookInvalid
.init(parameters
["InvalidLook"]);
227 _PrimLookInvalid
= _PrimLook
;
229 _Prim
.setLook(_PrimLook
);
230 if (parameters
["ArrayName"].isString())
232 _ArrayName
= parameters
["ArrayName"].toString();
234 // look for inaccessible parts (hardcoded for now)
235 CPrimLook inaccessibleLook
;
236 inaccessibleLook
.init(getEditor().getEnv()["PrimRender"]["RoadLookInaccessible"]);
237 inaccessibleLook
.Shape
= _PrimLook
.Shape
;
238 _InaccessiblePrim
.setLook(inaccessibleLook
);
241 //_Links.setShapeName(parameters["ShapeName"].toString());
246 // *********************************************************************************************************
247 CDisplayerVisualGroup::~CDisplayerVisualGroup()
253 // *********************************************************************************************************
254 void CDisplayerVisualGroup::setActive(bool active
)
256 //H_AUTO(R2_CDisplayerVisualGroup_setActive)
257 if (active
== _Active
) return;
258 CGroupMap
*worldMap
= CTool::getWorldMap();
263 if (!_Prim
.isAddedToWorldMap())
265 worldMap
->addDeco(&_Prim
);
270 if (_Prim
.isAddedToWorldMap())
272 worldMap
->removeDeco(&_Prim
);
274 if (_InaccessiblePrim
.isAddedToWorldMap())
276 worldMap
->removeDeco(&_InaccessiblePrim
);
291 // *********************************************************************************************************
292 bool CDisplayerVisualGroup::getActive() const
294 //H_AUTO(R2_CDisplayerVisualGroup_getActive)
299 // *********************************************************************************************************
300 void CDisplayerVisualGroup::onAttrModified(const std::string
&attrName
, sint32 attrIndex
)
302 //H_AUTO(R2_CDisplayerVisualGroup_onAttrModified)
303 CDisplayerVisual::onAttrModified(attrName
, attrIndex
);
304 // necessary to handle this because there no event for 'element removed from table' for now ...
305 if (attrName
== _ArrayName
)
309 /*else if (attrName == "DisplayMode")
316 // *********************************************************************************************************
317 void CDisplayerVisualGroup::setDisplayMode(sint32 mode
)
319 //H_AUTO(R2_CDisplayerVisualGroup_setDisplayMode)
320 CDisplayerVisual::setDisplayMode(mode
);
325 // *********************************************************************************************************
326 void CDisplayerVisualGroup::onParentDisplayModeChanged()
328 //H_AUTO(R2_CDisplayerVisualGroup_onParentDisplayModeChanged)
333 // *********************************************************************************************************
334 void CDisplayerVisualGroup::updateWorldPos()
336 //H_AUTO(R2_CDisplayerVisualGroup_updateWorldPos)
337 CDisplayerVisual::updateWorldPos();
338 // must update position on next display
340 _AccessibilityTouched
= true;
343 // *********************************************************************************************************
344 bool CDisplayerVisualGroup::isInProjection(const NLMISC::CVector2f
&pos
) const
346 if (!_DrawnThisFrame
) return false;
347 if ((sint
)_Prim
.getLook().Shape
== (sint
)ClosedPolyLine
)
350 if (_Poly2D
.contains(pos
, false)) return true;
352 // test intersection with all decals
353 return _Prim
.contains(pos
);
356 // *********************************************************************************************************
357 bool CDisplayerVisualGroup::isInProjectionBorder(const NLMISC::CVector2f
&pos
) const
359 if (isOnEdge(pos
) != -1)
366 // *********************************************************************************************************
367 sint
CDisplayerVisualGroup::isOnEdge(const NLMISC::CVector2f
&pos
) const
369 return _Prim
.isOnEdge(pos
);
372 // *********************************************************************************************************
373 uint
CDisplayerVisualGroup::getFadeTimeInMS() const
375 return (uint
) CV_RegionFadeTimeInMs
.get();
379 // *********************************************************************************************************
380 void CDisplayerVisualGroup::onPostRender()
382 if (!_Active
||!getActualVisibility()) return;
383 updatePrimVertices();
384 updateAccessibility();
387 // *********************************************************************************************************
388 bool CDisplayerVisualGroup::isAccessible()
390 updateAccessibility();
391 return !_CurrPrimInaccessible
;
394 // *********************************************************************************************************
395 void CDisplayerVisualGroup::updateAccessibility()
397 //H_AUTO(R2_CDisplayerVisualGroup_updateAccessibility)
398 if (getEditor().getIslandCollision().getPackedIsland() != _LastIsland
)
400 _AccessibilityTouched
= true;
403 if (!_AccessibilityTouched
) return;
406 // if not active, don't update the flag !!! This only is a display flag
407 // only npc group use the 'star' shape for now ...
408 _CurrPrimInaccessible
= false;
409 _AccessibilityTouched
= false;
412 _LastIsland
= getEditor().getIslandCollision().getPackedIsland();
413 updatePrimVertices();
414 uint numVerts
= (uint
)_Prim
.getVertices().size();
415 _CurrPrimInaccessible
= false;
416 // Old version : path should be accessible along the edges
418 if (_Prim.getLook().Shape != CPrimLook::ClosedPolyLine) -- numVerts;
419 for (uint k = 0; k < numVerts; ++k)
421 if (!getEditor().getIslandCollision().isValidSegment(_Prim.getVertices()[k], _Prim.getVertices()[(k + 1) % _Prim.getVertices().size()]))
423 _CurrPrimInaccessible = true;
428 // New version : path should be accessible at vertices only
429 for (uint k
= 0; k
< numVerts
; ++k
)
431 if (!getEditor().getIslandCollision().isValidPos(_Prim
.getVertices()[k
]))
433 _CurrPrimInaccessible
= true;
437 CGroupMap
*gm
= CTool::getWorldMap();
440 // error: no more display of inaccessible pos
442 if (_CurrPrimInaccessible)
444 _InaccessiblePrim.setVertices(_Prim.getVertices());
445 if (!_InaccessiblePrim.isAddedToWorldMap())
447 gm->addDeco(&_InaccessiblePrim);
452 if (_InaccessiblePrim.isAddedToWorldMap())
454 gm->removeDeco(&_InaccessiblePrim);
460 _AccessibilityTouched
= false;
463 // *********************************************************************************************************
464 void CDisplayerVisualGroup::updatePrimVertices()
466 //H_AUTO(R2_CDisplayerVisualGroup_updatePrimVertices)
467 if (!_Active
) return;
468 if (!_PrimTouched
) return;
469 updateInstanceList();
471 static std::vector
<NLMISC::CVector
> vertices
;
473 _Poly2D
.Vertices
.clear();
474 for(uint k
= 0; k
< _Instances
.size(); ++k
)
478 vertices
.push_back(_Instances
[k
]->evalLinkPoint(k
== 0 && _Prim
.getLook().Shape
== CPrimLook::Star
));
479 _Poly2D
.Vertices
.push_back(CVector(vertices
.back().x
, vertices
.back().y
, 0.f
));
483 nlwarning("_Instances[%d] == 0", k
);
487 if (_Prim
.getLook().Shape
== CPrimLook::ClosedPolyLine
)
494 // test against the collision map : all traversed opsition must be valid else poly is invalid
496 if (_PrimLook.Shape == CPrimLook::ClosedPolyLine)
498 // test concave poly against map
500 // test against water
505 // test polyline against map
506 R2::CScenarioEntryPoints::CCompleteIsland *island = getEditor().getIslandCollision().getCurrIslandDesc();
507 const NLMISC::CArray2D<sint16> &heightMap = getEditor().getIslandCollision().getHeightMap();
508 if (getEditor().getIslandCollision().getHeightMap())
512 // test against water
517 // if displayed on the map, set a first time to see if poly is invalid
518 if (_PrimLook
.Shape
== CPrimLook::ClosedPolyLine
)
520 if (_Prim
.getWorldMapPoly())
522 _Prim
.getWorldMapPoly()->setVertices(vertices
);
523 valid
= _Prim
.getWorldMapPoly()->isValid();
526 if (valid
!= _CurrPrimValid
)
528 _CurrPrimValid
= valid
;
531 _Prim
.setVertices(vertices
);
532 _PrimTouched
= false;
535 // *********************************************************************************************************
536 void CDisplayerVisualGroup::updateBoundingBox()
538 //H_AUTO(R2_CDisplayerVisualGroup_updateBoundingBox)
539 CLandscapePolyDrawer::computeBBoxFromPolygon(_Poly2D
, _BBox
);
542 // *********************************************************************************************************
543 void CDisplayerVisualGroup::updatePrimLook()
545 //H_AUTO(R2_CDisplayerVisualGroup_updatePrimLook)
546 TDisplayMode displayMode
= getActualDisplayMode();
547 // if contextual visibility is enabled, then see if really visible
548 if (displayMode
!= DisplayModeHidden
&& _ContextualVisibilityActive
&& getDisplayedInstance()->isKindOf("BasePrimitive"))
550 if (!isContextuallyVisible())
552 displayMode
= DisplayModeHidden
;
556 if (displayMode
== DisplayModeHidden
)
558 _Prim
.setActive(false);
559 _InaccessiblePrim
.setActive(false);
563 _Prim
.setActive(true);
564 _InaccessiblePrim
.setActive(true);
566 CPrimLook
&look
= (_CurrPrimValid
&& !_CurrPrimInaccessible
) ? _PrimLook
: _PrimLookInvalid
;
567 CRGBA oldEdgeWMCol
= look
.EdgeLook
.WorldMapColor
;
568 CRGBA oldEdgeDecalCol
= look
.EdgeLook
.DecalColor
;
569 CRGBA oldVertexWMCol
= look
.VertexLook
.WorldMapColor
;
570 CRGBA oldVertexDecalCol
= look
.VertexLook
.DecalColor
;
571 CRGBA oldFirstVertexWMCol
= look
.FirstVertexLook
.WorldMapColor
;
572 CRGBA oldFirstVertexDecalCol
= look
.FirstVertexLook
.DecalColor
;
577 case DisplayModeFrozen
:
578 col
= getBlinkColor(CV_MapEntityFrozenColor
.get());
581 case DisplayModeLocked
:
582 col
= getBlinkColor(CV_MapEntityLockedColor
.get());
588 if (getDisplayFlag(FlagSelected
) && !_CurrPrimInaccessible
)
590 // NB : don't want the highlight if not all parts are accessible
592 col
= CV_MapEntitySelectColor
.get();
595 else if (getDisplayFlag(FlagHasFocus
))
597 col
= CV_MapEntityHighlightColor
.get();
602 look
.EdgeLook
.WorldMapColor
= col
;
603 look
.EdgeLook
.DecalColor
= col
;
604 look
.VertexLook
.WorldMapColor
= col
;
605 look
.VertexLook
.DecalColor
= col
;
606 look
.FirstVertexLook
.WorldMapColor
= col
;
607 look
.FirstVertexLook
.DecalColor
= col
;
612 look
.EdgeLook
.WorldMapColor
= oldEdgeWMCol
;
613 look
.EdgeLook
.DecalColor
= oldEdgeDecalCol
;
614 look
.VertexLook
.WorldMapColor
= oldVertexWMCol
;
615 look
.VertexLook
.DecalColor
= oldVertexDecalCol
;
616 look
.FirstVertexLook
.WorldMapColor
= oldFirstVertexWMCol
;
617 look
.FirstVertexLook
.DecalColor
= oldFirstVertexDecalCol
;
621 // *********************************************************************************************************
622 void CDisplayerVisualGroup::onFocus(bool focused
)
624 //H_AUTO(R2_CDisplayerVisualGroup_onFocus)
625 CDisplayerVisual::onFocus(focused
);
629 // *********************************************************************************************************
630 void CDisplayerVisualGroup::onSelect(bool selected
)
632 //H_AUTO(R2_CDisplayerVisualGroup_onSelect)
633 CDisplayerVisual::onSelect(selected
);
637 // *********************************************************************************************************
638 void CDisplayerVisualGroup::onPreRender()
640 //H_AUTO(R2_CDisplayerVisualGroup_onPreRender)
641 _DrawnThisFrame
= false;
642 if (!_Active
) return;
643 // see if render is on for primitives (don't use a config var because may be dynamically changed)
644 //if (!getEditor().getConfig()["PrimDisplayEnabled"].toBoolean()) return;
645 _DrawnThisFrame
= true;
646 bool nowVisible
= getActualVisibility();
647 if (_VisibleLastFrame
!= nowVisible
)
652 _VisibleLastFrame
= nowVisible
;
653 if (!nowVisible
) return;
655 updatePrimVertices();
656 // progressive higlight
657 if (!getDisplayFlag(FlagSelected
))
659 if (getDisplayFlag(FlagHasFocus
))
662 if (_TimeOver
> getFadeTimeInMS())
664 _TimeOver
= getFadeTimeInMS();
680 float selectionFactor
= 0.f
;
683 uint fadeTime
= getFadeTimeInMS();
686 selectionFactor
= (float) _TimeOver
/ fadeTime
;
691 selectionFactor
= getDisplayFlag(FlagHasFocus
) ? 1.f
: 0.f
;
694 if (_Prim
.getLook().Shape
== CPrimLook::ClosedPolyLine
&& _CurrPrimValid
)
697 switch(getActualDisplayMode())
699 case DisplayModeVisible
:
700 baseColor
= CV_UnselectedRegionColor
.get();
702 case DisplayModeFrozen
:
703 baseColor
= CV_FrozenRegionColor
.get();
705 case DisplayModeLocked
:
706 baseColor
= CV_LockedRegionColor
.get();
709 baseColor
= CV_UnselectedRegionColor
.get();
713 if (getDisplayFlag(FlagSelected
))
715 polyColor
= CV_SelectedRegionColor
.get();
719 polyColor
= getBlinkColor(blend(baseColor
, CV_FocusedRegionColor
.get(), selectionFactor
));
721 _Prim
.setWorldMapPolyColor(polyColor
);
722 static volatile bool showPoly
= true;
725 CLandscapePolyDrawer::getInstance().addPoly(_Poly2D
, polyColor
, _BBox
);
729 if (getDisplayFlag(FlagSelected))
731 _Prim.setEmissive(getBlinkColor(CV_SelectedInstanceColor.get()));
735 _Prim.setEmissive(getBlinkColor(blend(CV_UnselectedInstanceColor.get(), CV_FocusedInstanceColor.get(), selectionFactor)));
739 _Prim
.addDecalsToRenderList();
741 if (_CurrPrimInaccessible
)
743 // CHANGE: no more display for inaccessible parts
744 // update color blinkking for inaccessible
745 /*CToolDrawPrim::updateInaccessiblePrimRenderLook(_InaccessiblePrim);
746 _InaccessiblePrim.addDecalsToRenderList();
753 // *********************************************************************************************************
754 void CDisplayerVisualGroup::updateInstanceList() const
756 //H_AUTO(R2_CDisplayerVisualGroup_updateInstanceList)
757 if (!_InstanceListTouched
) return;
758 _InstanceListTouched
= false;
760 const CObject
*sons
= getProps().getAttr(_ArrayName
);
762 if (sons
->getSize() == 0) return;
763 _Instances
.resize(sons
->getSize());
764 for(uint k
= 0; k
< sons
->getSize(); ++k
)
766 CInstance
*inst
= getEditor().getInstanceFromObject(sons
->getValueAtPos(k
));
769 _Instances
[k
] = inst
->getDisplayerVisual();
774 // *********************************************************************************************************
775 NLMISC::CVector
CDisplayerVisualGroup::evalLinkPoint(bool leader
)
777 //H_AUTO(R2_NLMISC_CVector )
778 updateInstanceList();
779 if (!_Instances
.empty())
781 return _Instances
[0]->evalLinkPoint(leader
);
785 nlwarning("_Instances[0] == 0");
786 return CVector::Null
;
791 // *********************************************************************************************************
792 NLMISC::CVector
CDisplayerVisualGroup::evalExitPoint()
794 //H_AUTO(R2_NLMISC_CVector )
795 updateInstanceList();
796 if (!_Instances
.empty())
798 return _Instances
.back()->evalLinkPoint();
802 nlwarning("_Instances[0] == 0");
803 return CVector::Null
;
808 // *********************************************************************************************************
809 bool CDisplayerVisualGroup::evalEnterPoint(const NLMISC::CVector
&startPoint
, NLMISC::CVector
&result
)
811 //H_AUTO(R2_CDisplayerVisualGroup_evalEnterPoint)
812 updateInstanceList();
813 if (_Prim
.getLook().Shape
!= CPrimLook::ClosedPolyLine
)
815 if (!_Instances
.empty())
817 result
= _Instances
[0]->getWorldPos().asVector();
822 _Poly2D
.Vertices
.resize(_Instances
.size());
823 for(uint k
= 0; k
< _Instances
.size(); ++k
)
825 _Poly2D
.Vertices
[k
] = _Instances
[k
]->getWorldPos().asVector();
827 if (_Poly2D
.contains(startPoint
, false))
831 float bestDist
= FLT_MAX
;
832 for(uint k
= 0; k
< _Instances
.size(); ++k
)
834 CVector v0
= _Instances
[k
]->getWorldPos().asVector();
835 CVector v1
= _Instances
[(k
+ 1) % _Instances
.size()]->getWorldPos().asVector();
839 float coord
= (startPoint
- v0
) * ((v1
- v0
).normed());
841 if (coord
>= 0 && coord
< (v1
- v0
).norm())
843 l
.project(startPoint
, proj
);
844 dist
= (proj
- startPoint
).norm();
852 dist
= (startPoint
- v0
).norm();
860 return bestDist
!= FLT_MAX
;
863 // *********************************************************************************************************
864 const NLMISC::CMatrix
&CDisplayerVisualGroup::getInvertedMatrix() const
866 //H_AUTO(R2_NLMISC_CMatrix )
867 return CMatrix::Identity
; // all coordinates are in world ...
870 // *********************************************************************************************************
871 void CDisplayerVisualGroup::getSonsWorldPos2f(std::vector
<NLMISC::CVector2f
> &result
)
873 //H_AUTO(R2_CDisplayerVisualGroup_getSonsWorldPos2f)
874 updateInstanceList();
876 for(uint k
= 0; k
< _Instances
.size(); ++k
)
878 result
.push_back(_Instances
[k
]->getWorldPos2f());
882 // *********************************************************************************************************
883 void CDisplayerVisualGroup::getSons(std::vector
<CDisplayerVisual
*> &sons
) const
885 //H_AUTO(R2_CDisplayerVisualGroup_getSons)
886 updateInstanceList();
888 sons
.insert(sons
.begin(), _Instances
.begin(), _Instances
.end());
891 // *********************************************************************************************************
892 uint
CDisplayerVisualGroup::getNumSons() const
894 //H_AUTO(R2_CDisplayerVisualGroup_getNumSons)
895 updateInstanceList();
896 return (uint
)_Instances
.size();
899 // *********************************************************************************************************
900 CDisplayerVisual
*CDisplayerVisualGroup::getSon(uint index
) const
902 //H_AUTO(R2_CDisplayerVisualGroup_getSon)
903 updateInstanceList();
904 nlassert(index
< _Instances
.size());
905 return _Instances
[index
];
908 // *********************************************************************************************************
909 void CDisplayerVisualGroup::setActiveRecurse(bool active
)
911 //H_AUTO(R2_CDisplayerVisualGroup_setActiveRecurse)
913 updateInstanceList();
914 for(uint k
= 0; k
< _Instances
.size(); ++k
)
916 _Instances
[k
]->setActive(active
);
920 // *********************************************************************************************************
921 void CDisplayerVisualGroup::setContextualVisibilityActive(bool active
)
923 //H_AUTO(R2_CDisplayerVisualGroup_setContextualVisibilityActive)
924 _ContextualVisibilityActive
= active
;
928 // *********************************************************************************************************
929 CDisplayerVisual::TDisplayMode
CDisplayerVisualGroup::getActualDisplayMode() const
931 //H_AUTO(R2_CDisplayerVisualGroup_getActualDisplayMode)
932 TDisplayMode dm
= CDisplayerVisual::getActualDisplayMode();
933 if (dm
== DisplayModeHidden
) return dm
;
934 if (!_ContextualVisibilityActive
|| const_cast<CDisplayerVisualGroup
*>(this)->isContextuallyVisible()) return dm
;
935 return DisplayModeHidden
;
939 // *********************************************************************************************************
940 bool CDisplayerVisualGroup::isContextuallyVisible()
942 //H_AUTO(R2_CDisplayerVisualGroup_isContextuallyVisible)
943 if (!_ContextualVisibilityActive
) return true;
944 const CInstance
*selection
= getEditor().getSelectedInstance();
947 if (this == selection
->getDisplayerVisual()) return true;
948 if (selection
->getDisplayerVisual() && selection
->getDisplayerVisual()->getParent() == this) return true;
950 return _ContextualVisibilityDate
== T1
;