CEntity* CEntityPool::GetEntityFromPool(bool &outIsActive, EntityId forcedPoolId /*= 0*/) { FUNCTION_PROFILER(GetISystem(), PROFILE_ENTITY); CEntity* pPoolEntity = NULL; if (forcedPoolId > 0) { pPoolEntity = GetPoolEntityWithPoolId(outIsActive, forcedPoolId); } if (!pPoolEntity) { pPoolEntity = GetPoolEntityFromInactiveSet(); if (pPoolEntity) outIsActive = false; } if (!pPoolEntity) { pPoolEntity = GetPoolEntityFromActiveSet(); if (pPoolEntity) outIsActive = true; } if (!pPoolEntity) { CRY_ASSERT_MESSAGE(false, "CEntityPool::GetEntityFromPool() Creating new entity for pool usage at run-time. Pool was too small!"); EntityWarning("[Entity Pool] Pool \'%s\' was too small. A new entity had to be created at run-time. Consider increasing the pool size.", m_sName.c_str()); #ifdef ENTITY_POOL_DEBUGGING m_bDebug_HasExpanded = true; #endif //ENTITY_POOL_DEBUGGING // Make sure not to go above the max size if (m_uMaxSize > 0 && m_InactivePoolIds.size() + m_ActivePoolIds.size() < m_uMaxSize) { // Make a new one if (!CreatePoolEntity(pPoolEntity, false)) { CRY_ASSERT_MESSAGE(false, "CEntityPool::GetEntityFromPool() Failed when creating a new pool entity."); } } else { CRY_ASSERT_MESSAGE(false, "CEntityPool::GetEntityFromPool() Have to create a new pool entity but am already at max size!"); EntityWarning("[Entity Pool] Pool \'%s\' has reached its max size and a new entity was requested. The new entity was not created!", m_sName.c_str()); } outIsActive = false; } return pPoolEntity; }
void CEntityObject::OnXForm( CEntity* pEntity ) { UpdateWorldTM(pEntity); if (!m_worldTM.IsValid()) { EntityWarning("CEntityObject::OnXForm: Invalid world matrix: %s", pEntity->GetEntityTextDescription()); return; } if (pLight) { ILightSource* pLightSource = pLight; // Update light positions. CDLight* pDLight = &pLightSource->GetLightProperties(); pDLight->SetPosition( m_worldTM.GetTranslation()); pDLight->SetMatrix(m_worldTM); pDLight->m_sName = pEntity->GetName(); // For debugging only. pDLight->m_nEntityId = pEntity->GetId(); pEntity->UpdateLightClipBounds(*pDLight); pLightSource->SetMatrix(m_worldTM); pLight->SetSrcEntity(pEntity); } else if (pChildRenderNode) { pChildRenderNode->SetMatrix( m_worldTM ); } }
CEntity* CEntityPool::GetPoolEntityFromActiveSet() { FUNCTION_PROFILER(GetISystem(), PROFILE_ENTITY); assert(!gEnv->IsEditor()); CEntity* pPoolEntity = NULL; assert(m_pEntityPoolManager); CEntitySystem* pEntitySystem = m_pEntityPoolManager->GetEntitySystem(); const uint32 uActiveSize = m_ActivePoolIds.size(); const bool bAtMax = (m_uMaxSize > 0 && uActiveSize >= m_uMaxSize); m_ReturnToPoolWeights.clear(); m_ReturnToPoolWeights.reserve(m_ActivePoolIds.size()); // Go through the active list and ask if any are available for removal TPoolIdsVec::iterator itPoolSlot = m_ActivePoolIds.begin(); TPoolIdsVec::iterator itPoolSlotEnd = m_ActivePoolIds.end(); for (; itPoolSlot != itPoolSlotEnd; ++itPoolSlot) { CEntity* pEntity = (CEntity*)pEntitySystem->GetEntity(itPoolSlot->usingId); if (!pEntity) { CRY_ASSERT_MESSAGE(pEntity, "NULL Pool Entity in Active set"); continue; } SReturnToPoolWeight returnToPoolWeight; returnToPoolWeight.pEntity = pEntity; returnToPoolWeight.weight = m_pEntityPoolManager->GetReturnToPoolWeight(pEntity, bAtMax); m_ReturnToPoolWeights.push_back(returnToPoolWeight); } // Sort and use top if weight > 0 if (!m_ReturnToPoolWeights.empty()) { std::sort(m_ReturnToPoolWeights.begin(), m_ReturnToPoolWeights.end()); SReturnToPoolWeight &bestEntry = m_ReturnToPoolWeights.front(); if (bestEntry.weight > FLT_EPSILON) { pPoolEntity = bestEntry.pEntity; #ifdef ENTITY_POOL_DEBUGGING if (bAtMax) { ++m_iDebug_TakenFromActiveForced; EntityWarning("[Entity Pool] Pool \'%s\' has reached its max size and a new entity was requested. An entity from the active set was forced to be reused: \'%s\' (%d)", m_sName.c_str(), pPoolEntity->GetName(), m_iDebug_TakenFromActiveForced); } #endif //ENTITY_POOL_DEBUGGING } } return pPoolEntity; }
bool CScriptProxy::GotoState( const char* sStateName ) { int nStateId = m_pScript->GetStateId( sStateName ); if (nStateId >= 0) { GotoState( nStateId ); } else { EntityWarning( "GotoState called with unknown state %s, in entity %s",sStateName,m_pEntity->GetEntityTextDescription()); return false; } return true; }
void CEntityClassRegistry::LoadClassDescription( XmlNodeRef &root,bool bOnlyNewClasses ) { assert( root != (IXmlNode*)NULL ); if (root->isTag("Entity")) { const char *sName = root->getAttr("Name"); if (*sName == 0) return; // Empty name. const char *sScript = root->getAttr("Script"); IEntityClass *pClass = FindClass( sName ); if (!pClass) { // New class. SEntityClassDesc cd; cd.flags = 0; cd.sName = sName; cd.sScriptFile = sScript; bool bInvisible = false; if (root->getAttr("Invisible",bInvisible)) { if (bInvisible) cd.flags |= ECLF_INVISIBLE; } bool bBBoxSelection = false; if (root->getAttr("BBoxSelection",bBBoxSelection)) { if (bBBoxSelection) cd.flags |= ECLF_BBOX_SELECTION; } RegisterStdClass( cd ); } else { // This class already registered. if (!bOnlyNewClasses) { EntityWarning( "[CEntityClassRegistry] LoadClassDescription failed, Entity Class name %s already registered",sName ); } } } }
IEntityClass* CEntityClassRegistry::RegisterStdClass( const SEntityClassDesc &entityClassDesc ) { // Creates a new entity class. CEntityClass *pClass = new CEntityClass; pClass->SetName(entityClassDesc.sName); pClass->SetFlags(entityClassDesc.flags); pClass->SetScriptFile(entityClassDesc.sScriptFile); pClass->SetUserProxyCreateFunc(entityClassDesc.pUserProxyCreateFunc, entityClassDesc.pUserProxyData); pClass->SetPropertyHandler(entityClassDesc.pPropertyHandler); pClass->SetEventHandler(entityClassDesc.pEventHandler); pClass->SetScriptFileHandler(entityClassDesc.pScriptFileHandler); pClass->SetEditorClassInfo(entityClassDesc.editorClassInfo); pClass->SetClassAttributes(entityClassDesc.classAttributes); pClass->SetEntityAttributes(entityClassDesc.entityAttributes); // Check if need to create entity script. if (entityClassDesc.sScriptFile[0] || entityClassDesc.pScriptTable) { // Create a new entity script. CEntityScript *pScript = new CEntityScript; bool ok = false; if(entityClassDesc.sScriptFile[0]) ok = pScript->Init(entityClassDesc.sName,entityClassDesc.sScriptFile); else ok = pScript->Init(entityClassDesc.sName, entityClassDesc.pScriptTable); if(!ok) { EntityWarning( "EntityScript %s failed to initialize",entityClassDesc.sScriptFile ); pScript->Release(); pClass->Release(); return NULL; } pClass->SetEntityScript( pScript ); } if (!RegisterEntityClass( pClass )) { // Register class failed. pClass->Release(); return NULL; } return pClass; }
bool CEntityClassRegistry::RegisterEntityClass( IEntityClass *pClass ) { assert( pClass != NULL ); bool newClass = false; if ((pClass->GetFlags() & ECLF_MODIFY_EXISTING) == 0) { IEntityClass *pOldClass = FindClass(pClass->GetName()); if (pOldClass) { EntityWarning( "CEntityClassRegistry::RegisterEntityClass failed, class with name %s already registered", pOldClass->GetName() ); return false; } newClass = true; } m_mapClassName[pClass->GetName()] = pClass; NotifyListeners(newClass ? ECRE_CLASS_REGISTERED : ECRE_CLASS_MODIFIED, pClass); return true; }
bool CEntityPool::ContainsEntityClass(IEntityClass* pClass) const { FUNCTION_PROFILER(GetISystem(), PROFILE_ENTITY); bool bClassValid = false; assert(m_pEntityPoolManager); TPoolDefinitionIds::const_iterator itDefinitionId = m_PoolDefinitionIds.begin(); TPoolDefinitionIds::const_iterator itDefinitionIdEnd = m_PoolDefinitionIds.end(); for (; !bClassValid && itDefinitionId != itDefinitionIdEnd; ++itDefinitionId) { const TEntityPoolDefinitionId definitionId = *itDefinitionId; const CEntityPoolDefinition* pDefinition = m_pEntityPoolManager->GetEntityPoolDefinition(definitionId); bClassValid = pDefinition && pDefinition->ContainsEntityClass(pClass); #ifdef ENTITY_POOL_SIGNATURE_TESTING if (bClassValid && CVar::es_TestPoolSignatures != 0) { assert(m_pEntityPoolManager); CEntitySystem* pEntitySystem = m_pEntityPoolManager->GetEntitySystem(); // Perform signature test on it to be sure by really spawning one bClassValid = pDefinition->TestEntityClassSignature(pEntitySystem, pClass, m_Signature); if (bClassValid) { CryLog("[Entity Pool] DEBUG: Signature passed for class \'%s\' to use Pool \'%s\'", pClass->GetName(), m_sName.c_str()); } else { EntityWarning("[Entity Pool] WARNING: DEBUG: Signature test failed for class \'%s\' using Pool \'%s\'", pClass->GetName(), m_sName.c_str()); continue; } } #endif //ENTITY_POOL_SIGNATURE_TESTING } return bClassValid; }
bool CEntityPool::CreatePool(const CEntityPoolDefinition &definition) { FUNCTION_PROFILER(GetISystem(), PROFILE_ENTITY); assert(!gEnv->IsEditor()); MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Other, EMemStatContextFlags::MSF_Instance, "Create Pool %s", definition.GetName().c_str()); m_sDefaultClass = definition.GetDefaultClass(); m_sName = definition.GetName(); m_bDefinitionHasAI |= definition.HasAI(); m_uMaxSize = definition.GetMaxSize(); const uint32 uCount = definition.GetDesiredPoolCount(); m_InactivePoolIds.reserve(uCount); CEntity* pPoolEntity = NULL; bool bResult = (CreatePoolEntity(pPoolEntity) && m_Signature.CalculateFromEntity(pPoolEntity)); if (bResult) { // Already created one, so create the remaining.. for (uint32 i = 1; i < uCount; ++i) { bResult &= CreatePoolEntity(pPoolEntity); } m_PoolDefinitionIds.push_back(definition.GetId()); } if (!bResult) { EntityWarning("CEntityPool::CreatePool() Failed when prepairing the Pool for the default class \'%s\'", m_sDefaultClass.c_str()); } return bResult; }
void CEntityObject::Render( CEntity* pEntity,SRendParams &rParams,int nRndFlags,CRenderProxy* pRenderProxy, const SRenderingPassInfo &passInfo ) { if (!bWorldTMValid) { UpdateWorldTM(pEntity); } // Override with custom slot material. IMaterial* pPrevMtl = rParams.pMaterial; if (pMaterial) rParams.pMaterial = pMaterial; int32 nOldObjectFlags = rParams.dwFObjFlags; rParams.dwFObjFlags |= dwFObjFlags; if (flags & ENTITY_SLOT_RENDER_AFTER_POSTPROCESSING) { rParams.dwFObjFlags |= FOB_RENDER_AFTER_POSTPROCESSING; } #ifdef SEG_WORLD rParams.nCustomFlags |= (1 << (COB_SW_SHIFT + pEntity->GetSwObjDebugFlag())); #endif // SEG_WORLD ////////////////////////////////////////////////////////////////////////// rParams.pInstance = this; const bool bIsInCameraSpace = (flags & ENTITY_SLOT_RENDER_NEAREST) != 0; // Draw static object. if (pStatObj) { rParams.pMatrix = &m_worldTM; rParams.dwFObjFlags |= FOB_TRANS_MASK; rParams.pFoliage = pFoliage; rParams.nSubObjHideMask = nSubObjHideMask; // make sure object motion blur can be applied to this object if (bObjectMoved) { rParams.dwFObjFlags |= FOB_DYNAMIC_OBJECT; bObjectMoved = false; } Matrix34 entityTM; if (bIsInCameraSpace) { rParams.pMatrix = &entityTM; entityTM = m_worldTM; // Camera space if (m_pCameraSpacePos) { // Use camera space relative position entityTM.SetTranslation(*m_pCameraSpacePos); } else { // We don't have camera space relative position, so calculate it out from world space // (This will not have the precision advantages of camera space rendering) entityTM.AddTranslation(-gEnv->pSystem->GetViewCamera().GetPosition()); } } if (rParams.pMatrix->IsValid()) pStatObj->Render( rParams, passInfo ); else EntityWarning("CEntityObject::Render: Invalid world matrix: %s", pEntity->GetEntityTextDescription()); } else if (pCharacter) { QuatTS Offset; Matrix34 PhysLocation(pEntity->GetWorldTM()); if (m_pXForm) Offset = QuatTS(m_pXForm->localTM); else { //CRY_FIXME(03,12,2009,"Animation & Rendering of entities needs to be re-written to avoid derivation of local offset due to float inaccuracy - Richard Semmens"); if (!Matrix34::IsEquivalent(PhysLocation,m_worldTM)) { Matrix34 invPhysLocation = PhysLocation.GetInverted(); Matrix34 matOffset = invPhysLocation * m_worldTM; Offset = QuatTS(matOffset); } else { Offset.SetIdentity(); } } if (bIsInCameraSpace) { // Camera space if (m_pCameraSpacePos) { // Use camera space relative position const Matrix33 camRot = Matrix33(gEnv->pSystem->GetViewCamera().GetViewMatrix()); PhysLocation.SetTranslation(*m_pCameraSpacePos * camRot); } else { // We don't have camera space relative position, so calculate it out from world space // (This will not have the precision advantages of camera space rendering) PhysLocation.AddTranslation(-gEnv->pSystem->GetViewCamera().GetPosition()); } Offset.SetIdentity(); } rParams.pMatrix = &PhysLocation; //rParams.pInstance = pCharacter; // Disable hand-placed (static) decals on characters rParams.dwFObjFlags |= FOB_DYNAMIC_OBJECT; pCharacter->Render(rParams, Offset, passInfo); const uint32 renderProxyFlags = pRenderProxy->GetFlags(); if (!passInfo.IsShadowPass() || (renderProxyFlags & CRenderProxy::FLAG_ANIMATE_OFFSCREEN_SHADOW)) { // If We render character, make sure it is also gets animation activated. if (!pEntity->m_bInActiveList) pEntity->ActivateForNumUpdates(8); } } else if (pChildRenderNode) { rParams.pMatrix = &m_worldTM; //rParams.pInstance = pChildRenderNode; pChildRenderNode->m_dwRndFlags = nRndFlags; pChildRenderNode->Render( rParams, passInfo ); } rParams.pMaterial = pPrevMtl; rParams.dwFObjFlags = nOldObjectFlags; if (!passInfo.IsShadowPass()) // Should also ignore rendering into the recursion. { if (pFoliage) { pFoliage->SetFlags(pFoliage->GetFlags() & ~IFoliage::FLAG_FROZEN | -(int)(rParams.nMaterialLayers & MTL_LAYER_FROZEN) & IFoliage::FLAG_FROZEN); static ICVar* g_pWindActivationDist = gEnv->pConsole->GetCVar("e_FoliageWindActivationDist"); float maxdist = g_pWindActivationDist ? g_pWindActivationDist->GetFVal() : 0.0f; Vec3 pos = m_worldTM.GetTranslation(); if (pStatObj && (gEnv->pSystem->GetViewCamera().GetPosition() - pos).len2() < sqr(maxdist) && gEnv->p3DEngine->GetWind(AABB(pos),false).len2() > 101.0f) pStatObj->PhysicalizeFoliage(pEntity->GetPhysics(),m_worldTM,pFoliage,0,4); } } }
CEntity* CEntityPool::GetPoolEntityWithPoolId(bool &outIsActive, EntityId forcedPoolId) { FUNCTION_PROFILER(GetISystem(), PROFILE_ENTITY); assert(!gEnv->IsEditor()); CEntity* pPoolEntity = NULL; assert(m_pEntityPoolManager); CEntitySystem* pEntitySystem = m_pEntityPoolManager->GetEntitySystem(); bool bFound = false; if (!bFound) { TPoolIdsVec::iterator itPoolSlot = m_InactivePoolIds.begin(); TPoolIdsVec::iterator itPoolSlotEnd = m_InactivePoolIds.end(); for (; itPoolSlot != itPoolSlotEnd; ++itPoolSlot) { if (itPoolSlot->poolId == forcedPoolId) { pPoolEntity = (CEntity*)pEntitySystem->GetEntity(itPoolSlot->poolId); CRY_ASSERT_MESSAGE(pPoolEntity != NULL, "Found forcedPoolId in Inactive set, but it is NULL"); outIsActive = false; bFound = true; break; } } } if (!bFound) { TPoolIdsVec::iterator itPoolSlot = m_ActivePoolIds.begin(); TPoolIdsVec::iterator itPoolSlotEnd = m_ActivePoolIds.end(); for (; itPoolSlot != itPoolSlotEnd; ++itPoolSlot) { if (itPoolSlot->poolId == forcedPoolId) { CEntity* pEntity = (CEntity*)pEntitySystem->GetEntity(itPoolSlot->poolId); assert(pEntity); if (!pEntity) { CRY_ASSERT_MESSAGE(false, "Found invalid pool entity (entity NULL)."); EntityWarning("Found invalid pool entity (entity NULL)."); continue; } // Don't use active ones if (m_pEntityPoolManager->GetReturnToPoolWeight(pEntity, true) <= 0.0f) { CRY_ASSERT_MESSAGE(false, "Found forcedPoolId in Active set, but it cannot be used"); } else { pPoolEntity = pEntity; } outIsActive = true; bFound = true; break; } } } return pPoolEntity; }