Fix css style order when using external css files
[ryzomcore.git] / ryzom / client / src / r2 / displayer_visual_shape.cpp
blob9d7bba6bae4d4a9c197cf56fc2a2f327c787b921
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpch.h"
19 #include "displayer_visual_shape.h"
20 #include "instance.h"
21 #include "editor.h"
22 #include "r2_config.h"
23 #include "tool.h"
25 #include "../entity_cl.h"
26 #include "../global.h"
27 #include "../misc.h"
28 #include "../pacs_client.h"
29 #include "verbose_clock.h"
31 #include "nel/3d/u_instance_material.h"
32 #include "nel/3d/u_shape_bank.h"
33 #include "nel/3d/u_visual_collision_manager.h"
34 #include "nel/3d/u_visual_collision_entity.h"
36 #ifdef DEBUG_NEW
37 #define new DEBUG_NEW
38 #endif
40 using namespace NLMISC;
42 extern uint SkipFrame;
44 namespace R2
47 // *********************************************************************************************************
48 CDisplayerVisualShape::CDisplayerVisualShape(const std::string &shapeName, float scale, bool worldMapDisplay)
50 _ShapeName = shapeName;
51 _Scale = scale;
52 _Touched = true;
53 _BadShapeName = false;
54 _Active = false;
55 _VisualSnapToGroundDone = false;
56 _VisualCollisionEntity = NULL;
57 _WorldMapDisplay = worldMapDisplay;
60 // *********************************************************************************************************
61 CDisplayerVisualShape::~CDisplayerVisualShape()
63 deleteShape();
64 deleteVisualCollisionEntity();
67 // *********************************************************************************************************
68 void CDisplayerVisualShape::deleteVisualCollisionEntity()
70 //H_AUTO(R2_CDisplayerVisualShape_deleteVisualCollisionEntity)
71 if (CollisionManager)
73 if (_VisualCollisionEntity)
75 CollisionManager->deleteEntity(_VisualCollisionEntity);
76 _VisualCollisionEntity = NULL;
81 // *********************************************************************************************************
82 void CDisplayerVisualShape::deleteShape()
84 //H_AUTO(R2_CDisplayerVisualShape_deleteShape)
85 if (!_Instance.empty())
87 Scene->deleteInstance(_Instance);
89 if (_MapDeco.isAddedToMap())
91 CGroupMap *gm = CTool::getWorldMap();
92 if (gm)
94 gm->removeDeco(&_MapDeco);
99 // *********************************************************************************************************
100 void CDisplayerVisualShape::onPreRender()
102 //H_AUTO(R2_CDisplayerVisualShape_onPreRender)
103 if (SkipFrame != 0)
105 // a tp was done -> invalidate visual collision entity
106 deleteVisualCollisionEntity();
108 if (!_Instance.empty())
110 bool inIsland = false;
111 CIslandCollision &col = getEditor().getIslandCollision();
112 R2::CScenarioEntryPoints::CCompleteIsland *currIsland = col.getCurrIslandDesc();
113 if (currIsland)
115 inIsland = currIsland->isIn(getWorldPos2f());
117 if (getActualVisibility() && inIsland)
119 _Instance.show();
120 if (_WorldMapDisplay && !_MapDeco.getActive())
122 _MapDeco.setActive(true);
123 _Touched = true;
126 else
128 _Instance.hide();
129 _MapDeco.setActive(false);
132 if (!getActualVisibility()) return;
133 if (_BadShapeName) return;
134 if (_Active)
136 if (testNeedZEval()) _VisualSnapToGroundDone = false;
137 if (!_VisualSnapToGroundDone && SkipFrame == 0)
139 snapToGround(); // force visual snap to ground if not already done + icon update
142 if (!_Touched)
144 if (!_Instance.empty()) _BBoxMatrix = _Instance.getMatrix();
145 else _BBoxMatrix = CMatrix::Identity;
146 return;
148 if (_Active)
150 updateMapDeco();
151 if (_Instance.empty())
153 sint64 startTime = 0;
154 static volatile bool bench = false;
155 if (bench)
157 startTime = CTime::getPerformanceTime();
159 _Instance = Scene->createInstance(_ShapeName);
160 if (bench)
162 sint64 endTime = CTime::getPerformanceTime();
163 nlwarning("clip time = %.2f ms", 1000.f * CTime::ticksToSecond(endTime - startTime));
165 if (_Instance.empty())
167 _BadShapeName = true;
168 return;
170 _Instance.setTransformMode(NL3D::UTransform::DirectMatrix);
171 _Instance.enableCastShadowMap(true);
173 CMatrix instanceMat;
174 instanceMat.setScale(_Scale);
175 instanceMat.setPos(getWorldPos().asVector());
176 _Instance.setMatrix(instanceMat);
177 _VisualSnapToGroundDone = false;
178 visualSnapToGround(); // force visual snap to ground if not already done
180 else
182 if (!_Instance.empty())
184 Scene->deleteInstance(_Instance);
188 if (!_Instance.empty())
190 _BBoxMatrix = _Instance.getMatrix(); // ensure that bbox and shape displayed at same pos
191 // (events that modify the instance pos may be received after the display of this frame)
193 _MapDeco.setInvalidPosFlag(getDisplayFlag(FlagBadPos));
194 _Touched = false;
197 // *********************************************************************************************************
198 void CDisplayerVisualShape::drawBBox(NLMISC::CRGBA color) const
200 //H_AUTO(R2_CDisplayerVisualShape_drawBBox)
201 if (getRotateInProgress()) return; // no drawn while drawing (bbox moved one frame too late, must solve this)
202 NLMISC::CAABBox bbox;
203 _Instance.getShapeAABBox(bbox);
204 Driver->setModelMatrix(_BBoxMatrix);
205 ::drawBox(bbox.getMin(), bbox.getMax(), color);
208 // *********************************************************************************************************
209 void CDisplayerVisualShape::onPostRender()
211 //H_AUTO(R2_CDisplayerVisualShape_onPostRender)
212 if (!_Active || !getActualVisibility()) return;
213 if (_BadShapeName) return;
214 if (!_Instance.empty())
216 if (getDisplayFlag(FlagSelected))
218 //visualSnapToGround();
219 drawBBox(CRGBA::Green);
220 setEmissive(_Instance, getBlinkColor(CV_SelectedInstanceColor.get()));
222 else if (getDisplayFlag(FlagHasFocus))
224 //visualSnapToGround();
225 drawBBox(CRGBA::White);
226 setEmissive(_Instance, getBlinkColor(CV_FocusedInstanceColor.get()));
228 else
230 CRGBA color = getDisplayModeColorInScene();
231 setEmissive(_Instance, color);
232 ::makeInstanceTransparent(_Instance, color.A, color.A != 255);
235 CDisplayerVisual::onPostRender();
238 // *********************************************************************************************************
239 void CDisplayerVisualShape::onAttrModified(const std::string &name, sint32 index)
241 //H_AUTO(R2_CDisplayerVisualShape_onAttrModified)
242 CDisplayerVisual::onAttrModified(name, index);
243 if (name == "Position")
245 _VisualSnapToGroundDone = false;
246 _Touched = true;
248 /*else if (name == "DisplayMode")
250 updateMapDeco();
254 // *********************************************************************************************************
255 void CDisplayerVisualShape::setDisplayMode(sint32 mode)
257 //H_AUTO(R2_CDisplayerVisualShape_setDisplayMode)
258 CDisplayerVisual::setDisplayMode(mode);
259 updateMapDeco();
263 // *********************************************************************************************************
264 void CDisplayerVisualShape::onParentDisplayModeChanged()
266 //H_AUTO(R2_CDisplayerVisualShape_onParentDisplayModeChanged)
267 updateMapDeco();
270 // *********************************************************************************************************
271 void CDisplayerVisualShape::onFocus(bool focused)
273 //H_AUTO(R2_CDisplayerVisualShape_onFocus)
274 CDisplayerVisual::onFocus(focused);
275 updateMapDeco();
278 // *********************************************************************************************************
279 void CDisplayerVisualShape::onSelect(bool selected)
281 //H_AUTO(R2_CDisplayerVisualShape_onSelect)
282 CDisplayerVisual::onSelect(selected);
283 updateMapDeco();
287 // *********************************************************************************************************
288 void CDisplayerVisualShape::setActive(bool active)
290 //H_AUTO(R2_CDisplayerVisualShape_setActive)
291 if (active == _Active) return;
292 if (!active)
294 deleteShape();
296 else
298 if (!_MapDeco.isAddedToMap() && _WorldMapDisplay)
300 CGroupMap *gm = CTool::getWorldMap();
301 if (gm)
303 _MapDeco.setDisplayedInstance(getDisplayedInstance(), false);
304 gm->addDeco(&_MapDeco);
305 _MapDeco.invalidateCoords();
309 _Touched = true;
310 _Active = active;
313 // *********************************************************************************************************
314 void CDisplayerVisualShape::updateMapDeco()
316 //H_AUTO(R2_CDisplayerVisualShape_updateMapDeco)
317 if (_MapDeco.isAddedToMap())
319 CGroupMap *gm = CTool::getWorldMap();
320 if (gm)
322 _MapDeco.onUpdate(*gm);
323 _MapDeco.invalidateCoords();
328 // *********************************************************************************************************
329 bool CDisplayerVisualShape::getActive() const
331 //H_AUTO(R2_CDisplayerVisualShape_getActive)
332 return _Active;
335 // *********************************************************************************************************
336 bool CDisplayerVisualShape::init(const CLuaObject &parameters)
338 //H_AUTO(R2_CDisplayerVisualSh_initSape)
339 _ShapeName = parameters["ShapeName"].toString();
340 if (parameters["Scale"].isNumber())
342 _Scale = parameters["Scale"];
344 NL3D::UShapeBank *shapeBank= Driver->getShapeBank();
345 if (shapeBank)
347 shapeBank->buildSystemGeometryForshape(_ShapeName);
349 return CDisplayerVisual::init(parameters);
352 // *********************************************************************************************************
353 bool CDisplayerVisualShape::getLastClip() const
355 //H_AUTO(R2_CDisplayerVisualShape_getLastClip)
356 if (_Instance.empty()) return true;
357 return !_Instance.getLastClippedState();
360 // *********************************************************************************************************
361 NLMISC::CAABBox CDisplayerVisualShape::getSelectBox() const
363 //H_AUTO(R2_CDisplayerVisualShape_getSelectBox)
364 if (_Instance.empty()) return CDisplayerVisual::getSelectBox();
365 // TODO nico : cache the bbox
366 NLMISC::CAABBox bbox;
367 _Instance.getShapeAABBox(bbox);
368 bbox.setMinMax(_Scale * bbox.getMin(), _Scale * bbox.getMax());
369 return bbox;
372 // *********************************************************************************************************
373 float CDisplayerVisualShape::preciseIntersectionTest(const NLMISC::CVector &worldRayStart,const NLMISC::CVector &worldRayDir) const
375 //H_AUTO(R2_CDisplayerVisualShape_preciseIntersectionTest)
376 if (_Instance.empty()) return FLT_MAX;
377 if(_Instance.supportFastIntersect())
379 float dist2D, distZ;
380 if (const_cast<NL3D::UInstance &>(_Instance).fastIntersect(worldRayStart, worldRayDir, dist2D, distZ, false))
382 if (dist2D == 0.f)
384 return distZ;
388 return FLT_MAX;
391 // *********************************************************************************************************
392 const NLMISC::CMatrix &CDisplayerVisualShape::getInvertedMatrix() const
394 //H_AUTO(R2_CDisplayerVisualShape_getInvertedMatrix)
395 // no rot part for now
396 _InvertedMatrix.setPos(- getWorldPos().asVector());
397 return _InvertedMatrix;
400 // *********************************************************************************************************
401 void CDisplayerVisualShape::updateWorldPos()
403 //H_AUTO(R2_CDisplayerVisualShape_updateWorldPos)
404 CDisplayerVisual::updateWorldPos();
405 // must always snap pos (if world pos was modified because of parent move,
406 // in this case our relative pos remains unmodified)
407 _VisualSnapToGroundDone = false;
408 snapToGround();
409 updateMapDeco();
413 // *********************************************************************************************************
414 void CDisplayerVisualShape::snapToGround()
416 //H_AUTO(R2_CDisplayerVisualShape_snapToGround)
417 if (!GR)
419 return;
422 NLPACS::UGlobalPosition gpos = GR->retrievePosition(getWorldPos());
423 if (gpos.InstanceId != -1)
425 CVector snappedPos = GR->getGlobalPosition(gpos);
426 // locally modify the z
427 _WorldPos.z = snappedPos.z;
428 //setDisplayFlag(FlagBadPos, false);
430 else
432 //setDisplayFlag(FlagBadPos, true);
434 visualSnapToGround();
435 _Touched = true;
438 // *********************************************************************************************************
439 void CDisplayerVisualShape::visualSnapToGround()
441 //H_AUTO(R2_CDisplayerVisualShape_visualSnapToGround)
442 if (!_VisualSnapToGroundDone)
444 if (!_Instance.empty())
446 CMatrix mat = _Instance.getMatrix();
447 CVector pos3f = _WorldPos.asVector();
448 // VisualCollisionEntity's 'snap to ground' requires that the entity is not farther than 100 meters from it
449 // Eval first coarse height from height map + coarse collision mesh
450 CTool::TRayIntersectionType interType = CTool::NoIntersection;
451 static volatile bool coarseSnap = true;
452 if (coarseSnap)
454 CVector inter;
455 CTool::TRayIntersectionType interType = CTool::computeWorldMapIntersection(pos3f.x, pos3f.y, inter);
456 if (interType != CTool::NoIntersection)
458 pos3f.z = inter.z;
461 bool snapped = false;
462 if (CollisionManager)
464 // create if necessary
465 if (!_VisualCollisionEntity)
467 _VisualCollisionEntity = CollisionManager->createEntity();
469 // eval finer pos from previous pos
470 snapped = _VisualCollisionEntity->snapToGround(pos3f); // refine z from current pos
473 if (snapped || interType != CTool::NoIntersection) // take precise version or else default to coarsest one
475 _WorldPos.z = pos3f.z;
477 _VisualSnapToGroundDone = true;
478 mat.setPos(_WorldPos);
479 _Instance.setMatrix(mat);
484 // *********************************************************************************************************
485 NLMISC::CVector CDisplayerVisualShape::evalLinkPoint(bool /* leader */)
487 //H_AUTO(R2_CDisplayerVisualShape_evalLinkPoint)
488 if (!_Instance.empty())
490 visualSnapToGround();
491 // use the visual snapped pos instead
492 return _Instance.getMatrix().getPos();
494 // return position that is visually snapped to the ground
495 return _WorldPos;
499 // *********************************************************************************************************
500 void CDisplayerVisualShape::onAdd(CGroupMap &/* owner */)
502 //H_AUTO(R2_CDisplayerVisualShape_onAdd)
506 // *********************************************************************************************************
507 void CDisplayerVisualShape::onRemove(CGroupMap &/* owner */)
509 //H_AUTO(R2_CDisplayerVisualShape_onRemove)
512 // *********************************************************************************************************
513 void CDisplayerVisualShape::onPreRender(CGroupMap &/* owner */)
515 //H_AUTO(R2_CDisplayerVisualShape_onPreRender)
519 // *********************************************************************************************************
520 void CDisplayerVisualShape::onUpdate(CGroupMap &/* owner */)
522 //H_AUTO(R2_CDisplayerVisualShape_onUpdate)
529 } // R2