1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
19 #include "nel/misc/debug.h"
20 #include "nel/3d/instance_group_user.h"
21 #include "nel/3d/scene_user.h"
22 #include "nel/3d/mesh_multi_lod_instance.h"
23 #include "nel/3d/text_context_user.h"
24 #include "nel/3d/particle_system_model.h"
25 #include "nel/misc/path.h"
26 #include "nel/misc/file.h"
27 #include "nel/3d/u_instance.h"
29 using namespace NLMISC
;
39 // ***************************************************************************
41 UInstanceGroup
*UInstanceGroup::createInstanceGroup (const std::string
&instanceGroup
)
43 // Create the instance group
44 CInstanceGroupUser
*user
=new CInstanceGroupUser
;
47 if (!user
->init (instanceGroup
))
56 // return the good value
60 // ***************************************************************************
62 void UInstanceGroup::createInstanceGroupAsync (const std::string
&instanceGroup
, UInstanceGroup
**pIG
)
64 CAsyncFileManager3D::getInstance().loadIGUser (instanceGroup
, pIG
);
67 // ***************************************************************************
69 void UInstanceGroup::stopCreateInstanceGroupAsync (UInstanceGroup
**ppIG
)
71 // Theorically should stop the async file manager but the async file manager can only be stopped
72 // between tasks (a file reading) so that is no sense to do anything here
77 if (*ppIG
!= (UInstanceGroup
*)-1)
83 // ***************************************************************************
84 CInstanceGroupUser::CInstanceGroupUser()
86 /* ***********************************************
87 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
88 * It can be loaded/called through CAsyncFileManager for instance
89 * ***********************************************/
91 _AddToSceneState
= StateNotAdded
;
93 // set user info for possible get
94 _InstanceGroup
.setUserInterface(this);
97 // ***************************************************************************
98 CInstanceGroupUser::~CInstanceGroupUser()
100 /* ***********************************************
101 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
102 * It can be loaded/called through CAsyncFileManager for instance
103 * ***********************************************/
105 // ensure all instances proxys are deleted
106 removeInstancesUser();
109 // ***************************************************************************
110 bool CInstanceGroupUser::init (const std::string
&instanceGroup
, bool async
)
116 file
.setAsyncLoading(true);
117 file
.setCacheFileOnOpen(true);
119 std::string path
= CPath::lookup (instanceGroup
, false);
120 if (!path
.empty() && file
.open (path
))
122 // Serialize this class
126 _InstanceGroup
.serial (file
);
128 catch (const EStream
& e
)
130 // Avoid visual warning
147 // ***************************************************************************
148 void CInstanceGroupUser::setTransformNameCallback (ITransformName
*pTN
)
150 _InstanceGroup
.setTransformNameCallback (pTN
);
154 // ***************************************************************************
155 void CInstanceGroupUser::setAddRemoveInstanceCallback(IAddRemoveInstance
*callback
)
157 _InstanceGroup
.setAddRemoveInstanceCallback(callback
);
161 // ***************************************************************************
162 void CInstanceGroupUser::setIGAddBeginCallback(IIGAddBegin
*callback
)
164 _InstanceGroup
.setIGAddBeginCallback(callback
);
169 // ***************************************************************************
170 void CInstanceGroupUser::addToScene (class UScene
& scene
, UDriver
*driver
, uint selectedTexture
)
172 // Get driver pointer
173 IDriver
*cDriver
= driver
? NLMISC::safe_cast
<CDriverUser
*>(driver
)->getDriver() : NULL
;
176 addToScene (((CSceneUser
*)&scene
)->getScene(), cDriver
, selectedTexture
);
179 // ***************************************************************************
180 void CInstanceGroupUser::getInstanceMatrix(uint instanceNb
,NLMISC::CMatrix
&dest
) const
182 _InstanceGroup
.getInstanceMatrix(instanceNb
, dest
);
186 // ***************************************************************************
187 void CInstanceGroupUser::addToScene (class CScene
& scene
, IDriver
*driver
, uint selectedTexture
)
189 if (!_InstanceGroup
.addToScene (scene
, driver
, selectedTexture
))
191 // Fill in the vector and the map accelerating search of instance by names
192 for( uint32 i
= 0; i
< _InstanceGroup
._Instances
.size(); ++i
)
195 if (_InstanceGroup
._Instances
[i
] != NULL
)
197 // insert in map (may fail if double name)
198 stmp
= _InstanceGroup
.getInstanceName (i
);
199 _InstanceMap
.insert (map
<string
,CTransformShape
*>::value_type(stmp
, _InstanceGroup
._Instances
[i
]));
204 // ***************************************************************************
205 void CInstanceGroupUser::addToSceneAsync (class UScene
& scene
, UDriver
*driver
, uint selectedTexture
)
207 IDriver
*cDriver
= driver
? NLMISC::safe_cast
<CDriverUser
*>(driver
)->getDriver() : NULL
;
209 _InstanceGroup
.addToSceneAsync (((CSceneUser
*)&scene
)->getScene(), cDriver
, selectedTexture
);
210 _AddToSceneState
= StateAdding
;
211 _AddToSceneTempScene
= &scene
;
212 _AddToSceneTempDriver
= driver
;
215 // ***************************************************************************
216 void CInstanceGroupUser::stopAddToSceneAsync ()
218 _InstanceGroup
.stopAddToSceneAsync ();
221 // ***************************************************************************
222 UInstanceGroup::TState
CInstanceGroupUser::getAddToSceneState ()
224 UInstanceGroup::TState newState
= (UInstanceGroup::TState
)_InstanceGroup
.getAddToSceneState ();
225 if ((_AddToSceneState
== StateAdding
) && (newState
== StateAdded
))
227 // Fill in the vector and the map accelerating search of instance by names
228 for( uint32 i
= 0; i
< _InstanceGroup
._Instances
.size(); ++i
)
231 if (_InstanceGroup
._Instances
[i
] != NULL
)
233 // create but don't want to delete from scene, since added/removed with _InstanceGroup
234 // insert in map (may fail if double name)
235 stmp
= _InstanceGroup
.getInstanceName (i
);
236 _InstanceMap
.insert (map
<string
,CTransformShape
*>::value_type(stmp
, _InstanceGroup
._Instances
[i
]));
239 _AddToSceneState
= StateAdded
;
244 // ***************************************************************************
245 void CInstanceGroupUser::removeFromScene (class UScene
& scene
)
247 _InstanceGroup
.removeFromScene (((CSceneUser
*)&scene
)->getScene());
248 // Remove all instance user object in the array/map
249 removeInstancesUser();
252 // ***************************************************************************
253 uint
CInstanceGroupUser::getNumInstance () const
255 return _InstanceGroup
.getNumInstance ();
258 // ***************************************************************************
260 const std::string
& CInstanceGroupUser::getShapeName (uint instanceNb
) const
263 if (instanceNb
>=_InstanceGroup
.getNumInstance ())
264 nlerror("getShapeName*(): bad instance Id");
266 return _InstanceGroup
.getShapeName (instanceNb
);
269 // ***************************************************************************
270 const std::string
& CInstanceGroupUser::getInstanceName (uint instanceNb
) const
273 if (instanceNb
>=_InstanceGroup
.getNumInstance ())
274 nlerror("getInstanceName*(): bad instance Id");
276 return _InstanceGroup
.getInstanceName (instanceNb
);
279 // ***************************************************************************
280 const NLMISC::CVector
& CInstanceGroupUser::getInstancePos (uint instanceNb
) const
283 if (instanceNb
>=_InstanceGroup
.getNumInstance ())
284 nlerror("getInstancePos*(): bad instance Id");
286 return _InstanceGroup
.getInstancePos (instanceNb
);
289 // ***************************************************************************
290 const NLMISC::CQuat
& CInstanceGroupUser::getInstanceRot (uint instanceNb
) const
293 if (instanceNb
>=_InstanceGroup
.getNumInstance ())
294 nlerror("getInstanceRot*(): bad instance Id");
296 return _InstanceGroup
.getInstanceRot (instanceNb
);
299 // ***************************************************************************
300 const NLMISC::CVector
& CInstanceGroupUser::getInstanceScale (uint instanceNb
) const
303 if (instanceNb
>=_InstanceGroup
.getNumInstance ())
304 nlerror("getInstanceScale*(): bad instance Id");
306 return _InstanceGroup
.getInstanceScale (instanceNb
);
309 // ***************************************************************************
311 UInstance
CInstanceGroupUser::getByName (const std::string
&name
) const
313 map
<string
,CTransformShape
*>::const_iterator it
= _InstanceMap
.find (name
);
314 if (it
!= _InstanceMap
.end())
315 return UInstance (it
->second
);
320 // ***************************************************************************
321 sint
CInstanceGroupUser::getIndexByName(const std::string
&name
) const
323 map
<string
,CTransformShape
*>::const_iterator it
= _InstanceMap
.find (name
);
324 if (it
== _InstanceMap
.end()) return -1;
325 for(uint k
= 0; k
< _InstanceGroup
._Instances
.size(); ++k
)
327 if (_InstanceGroup
._Instances
[k
] == it
->second
) return (sint
) k
;
333 // ***************************************************************************
334 void CInstanceGroupUser::setBlendShapeFactor (const std::string
&bsName
, float rFactor
)
336 _InstanceGroup
.setBlendShapeFactor (bsName
, rFactor
);
339 // ***************************************************************************
341 void CInstanceGroupUser::createRoot (UScene
&scene
)
343 _InstanceGroup
.createRoot (((CSceneUser
*)&scene
)->getScene());
346 // ***************************************************************************
347 void CInstanceGroupUser::setClusterSystemForInstances (UInstanceGroup
*pClusterSystem
)
349 _InstanceGroup
.setClusterSystemForInstances (&((CInstanceGroupUser
*)pClusterSystem
)->_InstanceGroup
);
352 // ***************************************************************************
353 bool CInstanceGroupUser::linkToParentCluster(UInstanceGroup
*father
)
356 return _InstanceGroup
.linkToParent(&(NLMISC::safe_cast
<CInstanceGroupUser
*>(father
)->_InstanceGroup
));
359 nlwarning("Trying to link a cluster system to a NULL parent cluster");
364 // ***************************************************************************
365 void CInstanceGroupUser::getDynamicPortals (std::vector
<std::string
> &names
)
367 _InstanceGroup
.getDynamicPortals (names
);
370 // ***************************************************************************
371 void CInstanceGroupUser::setDynamicPortal (std::string
& name
, bool opened
)
373 _InstanceGroup
.setDynamicPortal (name
, opened
);
376 // ***************************************************************************
377 bool CInstanceGroupUser::getDynamicPortal (std::string
& name
)
379 return _InstanceGroup
.getDynamicPortal (name
);
382 // ***************************************************************************
383 void CInstanceGroupUser::setPos (const NLMISC::CVector
&pos
)
385 _InstanceGroup
.setPos (pos
);
388 // ***************************************************************************
389 void CInstanceGroupUser::setRotQuat (const NLMISC::CQuat
&q
)
391 _InstanceGroup
.setRotQuat (q
);
394 // ***************************************************************************
395 CVector
CInstanceGroupUser::getPos ()
397 return _InstanceGroup
.getPos ();
400 // ***************************************************************************
401 CQuat
CInstanceGroupUser::getRotQuat ()
403 return _InstanceGroup
.getRotQuat();
407 // ***************************************************************************
408 void CInstanceGroupUser::freezeHRC()
410 _InstanceGroup
.freezeHRC();
413 // ***************************************************************************
414 void CInstanceGroupUser::unfreezeHRC()
416 _InstanceGroup
.unfreezeHRC();
420 // ***************************************************************************
421 bool CInstanceGroupUser::getStaticLightSetup(NLMISC::CRGBA sunAmbient
,
422 uint retrieverIdentifier
, sint surfaceId
, const NLMISC::CVector
&localPos
,
423 std::vector
<CPointLightInfluence
> &pointLightList
, uint8
&sunContribution
, NLMISC::CRGBA
&localAmbient
)
425 return _InstanceGroup
.getStaticLightSetup(sunAmbient
, retrieverIdentifier
, surfaceId
, localPos
, pointLightList
,
426 sunContribution
, localAmbient
);
429 // ***************************************************************************
430 /*virtual*/ void CInstanceGroupUser::setDistMax(uint instance
, float dist
)
432 if (instance
> _InstanceGroup
.getNumInstance())
434 nlwarning("CInstanceGroupUser::setDistMax : instance index %d is invalid", instance
);
437 if (_InstanceGroup
._Instances
[instance
]) _InstanceGroup
._Instances
[instance
]->setDistMax(dist
);
440 // ***************************************************************************
441 /*virtual*/ float CInstanceGroupUser::getDistMax(uint instance
) const
443 if (instance
> _InstanceGroup
.getNumInstance())
445 nlwarning("CInstanceGroupUser::getDistMax : instance index %d is invalid", instance
);
448 if (_InstanceGroup
._Instances
[instance
]) return _InstanceGroup
._Instances
[instance
]->getDistMax();
452 // ***************************************************************************
453 /*virtual*/ void CInstanceGroupUser::setCoarseMeshDist(uint instance
, float dist
)
455 if (instance
> _InstanceGroup
.getNumInstance())
457 nlwarning("CInstanceGroupUser::setCoarseMeshDist : instance index %d is invalid", instance
);
460 if (_InstanceGroup
._Instances
[instance
])
462 CMeshMultiLodInstance
*mmli
= dynamic_cast<CMeshMultiLodInstance
*>(_InstanceGroup
._Instances
[instance
]);
463 if (mmli
) mmli
->setCoarseMeshDist(dist
);
467 // ***************************************************************************
468 /*virtual*/ float CInstanceGroupUser::getCoarseMeshDist(uint instance
) const
470 if (instance
> _InstanceGroup
.getNumInstance())
472 nlwarning("getCoarseMeshDist::getDistMax : instance index %d is invalid", instance
);
475 if (_InstanceGroup
._Instances
[instance
])
477 CMeshMultiLodInstance
*mmli
= dynamic_cast<CMeshMultiLodInstance
*>(_InstanceGroup
._Instances
[instance
]);
478 if (mmli
) return mmli
->getCoarseMeshDist();
484 // ***************************************************************************
485 UInstance
CInstanceGroupUser::getInstance (uint instanceNb
) const
487 if(instanceNb
<_InstanceGroup
._Instances
.size())
488 return UInstance (_InstanceGroup
._Instances
[instanceNb
]);
493 // ***************************************************************************
494 void CInstanceGroupUser::removeInstancesUser()
496 /* ***********************************************
497 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
498 * It can be loaded/called through CAsyncFileManager for instance
499 * ***********************************************/
501 // clear the array and the map
502 _InstanceMap
.clear();
505 // ***************************************************************************
506 UInstanceGroup
*CInstanceGroupUser::getParentCluster() const
508 CInstanceGroup
*parent
= _InstanceGroup
.getParentClusterSystem();
510 // NB: return NULL if this is the GlobalInstanceGroup.
511 return parent
->getUserInterface();
516 // ***************************************************************************
517 void CInstanceGroupUser::displayDebugClusters(UDriver
*drv
, UTextContext
*txtCtx
)
521 CTextContext
*pTxtCtx
= NULL
;
523 pTxtCtx
= &((CTextContextUser
*)txtCtx
)->getTextContext();
524 _InstanceGroup
.displayDebugClusters(((CDriverUser
*)drv
)->getDriver(), pTxtCtx
);
526 // restore the matrix context cause of font rendering
527 ((CDriverUser
*)drv
)->restoreMatrixContext();
530 // ***************************************************************************
531 bool CInstanceGroupUser::dontCastShadowForInterior(uint instance
) const
533 if (instance
>=_InstanceGroup
.getNumInstance ())
535 return _InstanceGroup
.getInstance(instance
).DontCastShadowForInterior
;
538 // ***************************************************************************
539 bool CInstanceGroupUser::dontCastShadowForExterior(uint instance
) const
541 if (instance
>=_InstanceGroup
.getNumInstance ())
543 return _InstanceGroup
.getInstance(instance
).DontCastShadowForExterior
;