// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "std3d.h" #include "nel/misc/debug.h" #include "nel/3d/instance_group_user.h" #include "nel/3d/scene_user.h" #include "nel/3d/mesh_multi_lod_instance.h" #include "nel/3d/text_context_user.h" #include "nel/3d/particle_system_model.h" #include "nel/misc/path.h" #include "nel/misc/file.h" #include "nel/3d/u_instance.h" using namespace NLMISC; using namespace std; namespace NL3D { // *************************************************************************** UInstanceGroup *UInstanceGroup::createInstanceGroup (const std::string &instanceGroup) { // Create the instance group CInstanceGroupUser *user=new CInstanceGroupUser; // Init the class if (!user->init (instanceGroup)) { // Prb, erase it delete user; // Return error code return NULL; } // return the good value return user; } // *************************************************************************** void UInstanceGroup::createInstanceGroupAsync (const std::string &instanceGroup, UInstanceGroup **pIG) { CAsyncFileManager3D::getInstance().loadIGUser (instanceGroup, pIG); } // *************************************************************************** void UInstanceGroup::stopCreateInstanceGroupAsync (UInstanceGroup **ppIG) { // Theorically should stop the async file manager but the async file manager can only be stopped // between tasks (a file reading) so that is no sense to do anything here while (*ppIG == NULL) { nlSleep (2); } if (*ppIG != (UInstanceGroup*)-1) { delete *ppIG; } } // *************************************************************************** CInstanceGroupUser::CInstanceGroupUser() { /* *********************************************** * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance * It can be loaded/called through CAsyncFileManager for instance * ***********************************************/ _AddToSceneState = StateNotAdded; // set user info for possible get _InstanceGroup.setUserInterface(this); } // *************************************************************************** CInstanceGroupUser::~CInstanceGroupUser() { /* *********************************************** * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance * It can be loaded/called through CAsyncFileManager for instance * ***********************************************/ // ensure all instances proxys are deleted removeInstancesUser(); } // *************************************************************************** bool CInstanceGroupUser::init (const std::string &instanceGroup, bool async) { // Create a file CIFile file; if(async) { file.setAsyncLoading(true); file.setCacheFileOnOpen(true); } std::string path = CPath::lookup (instanceGroup, false); if (!path.empty() && file.open (path)) { // Serialize this class try { // Read the class _InstanceGroup.serial (file); } catch (const EStream& e) { // Avoid visual warning EStream ee=e; // Serial problem return false; } } else { // Failed. return false; } // Ok return true; } // *************************************************************************** void CInstanceGroupUser::setTransformNameCallback (ITransformName *pTN) { _InstanceGroup.setTransformNameCallback (pTN); } // *************************************************************************** void CInstanceGroupUser::setAddRemoveInstanceCallback(IAddRemoveInstance *callback) { _InstanceGroup.setAddRemoveInstanceCallback(callback); } // *************************************************************************** void CInstanceGroupUser::setIGAddBeginCallback(IIGAddBegin *callback) { _InstanceGroup.setIGAddBeginCallback(callback); } // *************************************************************************** void CInstanceGroupUser::addToScene (class UScene& scene, UDriver *driver, uint selectedTexture) { // Get driver pointer IDriver *cDriver= driver ? NLMISC::safe_cast(driver)->getDriver() : NULL; // Add to the scene addToScene (((CSceneUser*)&scene)->getScene(), cDriver, selectedTexture); } // *************************************************************************** void CInstanceGroupUser::getInstanceMatrix(uint instanceNb,NLMISC::CMatrix &dest) const { _InstanceGroup.getInstanceMatrix(instanceNb, dest); } // *************************************************************************** void CInstanceGroupUser::addToScene (class CScene& scene, IDriver *driver, uint selectedTexture) { if (!_InstanceGroup.addToScene (scene, driver, selectedTexture)) return; // Fill in the vector and the map accelerating search of instance by names for( uint32 i = 0; i < _InstanceGroup._Instances.size(); ++i) { string stmp; if (_InstanceGroup._Instances[i] != NULL) { // insert in map (may fail if double name) stmp = _InstanceGroup.getInstanceName (i); _InstanceMap.insert (map::value_type(stmp, _InstanceGroup._Instances[i])); } } } // *************************************************************************** void CInstanceGroupUser::addToSceneAsync (class UScene& scene, UDriver *driver, uint selectedTexture) { IDriver *cDriver= driver ? NLMISC::safe_cast(driver)->getDriver() : NULL; // Add to the scene _InstanceGroup.addToSceneAsync (((CSceneUser*)&scene)->getScene(), cDriver, selectedTexture); _AddToSceneState = StateAdding; _AddToSceneTempScene = &scene; _AddToSceneTempDriver = driver; } // *************************************************************************** void CInstanceGroupUser::stopAddToSceneAsync () { _InstanceGroup.stopAddToSceneAsync (); } // *************************************************************************** UInstanceGroup::TState CInstanceGroupUser::getAddToSceneState () { UInstanceGroup::TState newState = (UInstanceGroup::TState)_InstanceGroup.getAddToSceneState (); if ((_AddToSceneState == StateAdding) && (newState == StateAdded)) { // Fill in the vector and the map accelerating search of instance by names for( uint32 i = 0; i < _InstanceGroup._Instances.size(); ++i) { string stmp; if (_InstanceGroup._Instances[i] != NULL) { // create but don't want to delete from scene, since added/removed with _InstanceGroup // insert in map (may fail if double name) stmp = _InstanceGroup.getInstanceName (i); _InstanceMap.insert (map::value_type(stmp, _InstanceGroup._Instances[i])); } } _AddToSceneState = StateAdded; } return newState; } // *************************************************************************** void CInstanceGroupUser::removeFromScene (class UScene& scene) { _InstanceGroup.removeFromScene (((CSceneUser*)&scene)->getScene()); // Remove all instance user object in the array/map removeInstancesUser(); } // *************************************************************************** uint CInstanceGroupUser::getNumInstance () const { return _InstanceGroup.getNumInstance (); } // *************************************************************************** const std::string& CInstanceGroupUser::getShapeName (uint instanceNb) const { // Check args if (instanceNb>=_InstanceGroup.getNumInstance ()) nlerror("getShapeName*(): bad instance Id"); return _InstanceGroup.getShapeName (instanceNb); } // *************************************************************************** const std::string& CInstanceGroupUser::getInstanceName (uint instanceNb) const { // Check args if (instanceNb>=_InstanceGroup.getNumInstance ()) nlerror("getInstanceName*(): bad instance Id"); return _InstanceGroup.getInstanceName (instanceNb); } // *************************************************************************** const NLMISC::CVector& CInstanceGroupUser::getInstancePos (uint instanceNb) const { // Check args if (instanceNb>=_InstanceGroup.getNumInstance ()) nlerror("getInstancePos*(): bad instance Id"); return _InstanceGroup.getInstancePos (instanceNb); } // *************************************************************************** const NLMISC::CQuat& CInstanceGroupUser::getInstanceRot (uint instanceNb) const { // Check args if (instanceNb>=_InstanceGroup.getNumInstance ()) nlerror("getInstanceRot*(): bad instance Id"); return _InstanceGroup.getInstanceRot (instanceNb); } // *************************************************************************** const NLMISC::CVector& CInstanceGroupUser::getInstanceScale (uint instanceNb) const { // Check args if (instanceNb>=_InstanceGroup.getNumInstance ()) nlerror("getInstanceScale*(): bad instance Id"); return _InstanceGroup.getInstanceScale (instanceNb); } // *************************************************************************** UInstance CInstanceGroupUser::getByName (const std::string &name) const { map::const_iterator it = _InstanceMap.find (name); if (it != _InstanceMap.end()) return UInstance (it->second); else return UInstance (); } // *************************************************************************** sint CInstanceGroupUser::getIndexByName(const std::string &name) const { map::const_iterator it = _InstanceMap.find (name); if (it == _InstanceMap.end()) return -1; for(uint k = 0; k < _InstanceGroup._Instances.size(); ++k) { if (_InstanceGroup._Instances[k] == it->second) return (sint) k; } return -1; } // *************************************************************************** void CInstanceGroupUser::setBlendShapeFactor (const std::string &bsName, float rFactor) { _InstanceGroup.setBlendShapeFactor (bsName, rFactor); } // *************************************************************************** void CInstanceGroupUser::createRoot (UScene &scene) { _InstanceGroup.createRoot (((CSceneUser*)&scene)->getScene()); } // *************************************************************************** void CInstanceGroupUser::setClusterSystemForInstances (UInstanceGroup *pClusterSystem) { _InstanceGroup.setClusterSystemForInstances (&((CInstanceGroupUser*)pClusterSystem)->_InstanceGroup); } // *************************************************************************** bool CInstanceGroupUser::linkToParentCluster(UInstanceGroup *father) { if (father) return _InstanceGroup.linkToParent(&(NLMISC::safe_cast(father)->_InstanceGroup)); else { nlwarning("Trying to link a cluster system to a NULL parent cluster"); return false; } } // *************************************************************************** void CInstanceGroupUser::getDynamicPortals (std::vector &names) { _InstanceGroup.getDynamicPortals (names); } // *************************************************************************** void CInstanceGroupUser::setDynamicPortal (std::string& name, bool opened) { _InstanceGroup.setDynamicPortal (name, opened); } // *************************************************************************** bool CInstanceGroupUser::getDynamicPortal (std::string& name) { return _InstanceGroup.getDynamicPortal (name); } // *************************************************************************** void CInstanceGroupUser::setPos (const NLMISC::CVector &pos) { _InstanceGroup.setPos (pos); } // *************************************************************************** void CInstanceGroupUser::setRotQuat (const NLMISC::CQuat &q) { _InstanceGroup.setRotQuat (q); } // *************************************************************************** CVector CInstanceGroupUser::getPos () { return _InstanceGroup.getPos (); } // *************************************************************************** CQuat CInstanceGroupUser::getRotQuat () { return _InstanceGroup.getRotQuat(); } // *************************************************************************** void CInstanceGroupUser::freezeHRC() { _InstanceGroup.freezeHRC(); } // *************************************************************************** void CInstanceGroupUser::unfreezeHRC() { _InstanceGroup.unfreezeHRC(); } // *************************************************************************** bool CInstanceGroupUser::getStaticLightSetup(NLMISC::CRGBA sunAmbient, uint retrieverIdentifier, sint surfaceId, const NLMISC::CVector &localPos, std::vector &pointLightList, uint8 &sunContribution, NLMISC::CRGBA &localAmbient) { return _InstanceGroup.getStaticLightSetup(sunAmbient, retrieverIdentifier, surfaceId, localPos, pointLightList, sunContribution, localAmbient); } // *************************************************************************** /*virtual*/ void CInstanceGroupUser::setDistMax(uint instance, float dist) { if (instance > _InstanceGroup.getNumInstance()) { nlwarning("CInstanceGroupUser::setDistMax : instance index %d is invalid", instance); return; } if (_InstanceGroup._Instances[instance]) _InstanceGroup._Instances[instance]->setDistMax(dist); } // *************************************************************************** /*virtual*/ float CInstanceGroupUser::getDistMax(uint instance) const { if (instance > _InstanceGroup.getNumInstance()) { nlwarning("CInstanceGroupUser::getDistMax : instance index %d is invalid", instance); return -1.f; } if (_InstanceGroup._Instances[instance]) return _InstanceGroup._Instances[instance]->getDistMax(); else return -1.f; } // *************************************************************************** /*virtual*/ void CInstanceGroupUser::setCoarseMeshDist(uint instance, float dist) { if (instance > _InstanceGroup.getNumInstance()) { nlwarning("CInstanceGroupUser::setCoarseMeshDist : instance index %d is invalid", instance); return; } if (_InstanceGroup._Instances[instance]) { CMeshMultiLodInstance *mmli = dynamic_cast(_InstanceGroup._Instances[instance]); if (mmli) mmli->setCoarseMeshDist(dist); } } // *************************************************************************** /*virtual*/ float CInstanceGroupUser::getCoarseMeshDist(uint instance) const { if (instance > _InstanceGroup.getNumInstance()) { nlwarning("getCoarseMeshDist::getDistMax : instance index %d is invalid", instance); return -1.f; } if (_InstanceGroup._Instances[instance]) { CMeshMultiLodInstance *mmli = dynamic_cast(_InstanceGroup._Instances[instance]); if (mmli) return mmli->getCoarseMeshDist(); else return -1.f; } else return -1.f; } // *************************************************************************** UInstance CInstanceGroupUser::getInstance (uint instanceNb) const { if(instanceNb<_InstanceGroup._Instances.size()) return UInstance (_InstanceGroup._Instances[instanceNb]); else return UInstance (); } // *************************************************************************** void CInstanceGroupUser::removeInstancesUser() { /* *********************************************** * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance * It can be loaded/called through CAsyncFileManager for instance * ***********************************************/ // clear the array and the map _InstanceMap.clear(); } // *************************************************************************** UInstanceGroup *CInstanceGroupUser::getParentCluster() const { CInstanceGroup *parent= _InstanceGroup.getParentClusterSystem(); if(parent) // NB: return NULL if this is the GlobalInstanceGroup. return parent->getUserInterface(); else return NULL; } // *************************************************************************** void CInstanceGroupUser::displayDebugClusters(UDriver *drv, UTextContext *txtCtx) { if(!drv) return; CTextContext *pTxtCtx= NULL; if(txtCtx) pTxtCtx= &((CTextContextUser*)txtCtx)->getTextContext(); _InstanceGroup.displayDebugClusters(((CDriverUser*)drv)->getDriver(), pTxtCtx); // restore the matrix context cause of font rendering ((CDriverUser*)drv)->restoreMatrixContext(); } // *************************************************************************** bool CInstanceGroupUser::dontCastShadowForInterior(uint instance) const { if (instance>=_InstanceGroup.getNumInstance ()) return false; return _InstanceGroup.getInstance(instance).DontCastShadowForInterior; } // *************************************************************************** bool CInstanceGroupUser::dontCastShadowForExterior(uint instance) const { if (instance>=_InstanceGroup.getNumInstance ()) return false; return _InstanceGroup.getInstance(instance).DontCastShadowForExterior; } } // NL3D