예제 #1
0
//------------------------------------------------------------------------
bool CVehiclePartAnimated::ChangeState(EVehiclePartState state, int flags)
{
	if ((state == eVGS_Default) && m_initialiseOnChangeState)
	{
		// Initialise!
		// Having to do this because of the way the glass code
		// swaps a cstatobj. The way the vehicle code stores its
		// statobj in m_intactStatObjs is going to need reviewing
		if (m_pCharInstance)
		{
			ISkeletonPose*    pSkeletonPose                     = m_pCharInstance->GetISkeletonPose();
			IDefaultSkeleton &rIDefaultSkeleton                 = m_pCharInstance->GetIDefaultSkeleton();
			ISkeletonPose*    pSkeletonPoseDestroyed            = m_pCharInstanceDestroyed ? m_pCharInstanceDestroyed->GetISkeletonPose() : NULL;
			IDefaultSkeleton* pICharacterModelSkeletonDestroyed = m_pCharInstanceDestroyed ? &m_pCharInstanceDestroyed->GetIDefaultSkeleton() : NULL;
			if (pSkeletonPose)
			{
				const bool bDestroyedSkelExists = pSkeletonPoseDestroyed && pICharacterModelSkeletonDestroyed;
				for (uint32 i = 0; i < rIDefaultSkeleton.GetJointCount(); i++)
				{
					if (IStatObj* pStatObjIntact = pSkeletonPose->GetStatObjOnJoint(i))
					{
						const char* jointName = rIDefaultSkeleton.GetJointNameByID(i);

						if (m_intactStatObjs.find(CONST_TEMP_STRING(jointName)) == m_intactStatObjs.end())
						{
							m_intactStatObjs.insert(TStringStatObjMap::value_type(jointName, pStatObjIntact));
						}

						// tell the streaming engine to stream destroyed version together with non destroyed
						if (bDestroyedSkelExists && i < pICharacterModelSkeletonDestroyed->GetJointCount())
						{
							if (IStatObj* pStatObjIntactDestroyed = pSkeletonPoseDestroyed->GetStatObjOnJoint(i))
							{
								pStatObjIntact->SetStreamingDependencyFilePath(pStatObjIntactDestroyed->GetFilePath());
							}
						}
					}
				}
			}
		}
		m_initialiseOnChangeState = false;
	}

	bool change = CVehiclePartBase::ChangeState(state, flags);

	if (state == eVGS_Default && !change)
	{
		// need to restore state if one of the children is in higher state
		EVehiclePartState maxState = GetMaxState();

		if (maxState > m_state)
			change = true;
	}

	if (!change)
	{
		return false;
	}

	if (state == eVGS_Destroyed)
	{
		if (m_ignoreDestroyedState)
			return false;

		if (m_pCharInstance && m_pCharInstanceDestroyed)
		{
			ISkeletonPose*    pSkeletonPose     = m_pCharInstance->GetISkeletonPose();
			IDefaultSkeleton &rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton();
			if (pSkeletonPose)
			{
				IMaterial* pDestroyedMaterial = m_pVehicle->GetDestroyedMaterial();

				for (uint32 i = 0; i < rIDefaultSkeleton.GetJointCount(); i++)
				{
					if (IStatObj* pStatObjIntact = pSkeletonPose->GetStatObjOnJoint(i))
					{
						const char* jointName = rIDefaultSkeleton.GetJointNameByID(i);
						IStatObj*   pStatObj  = GetDestroyedGeometry(jointName);

						// sets new StatObj to joint, if null, removes it.
						// object whose name includes "proxy" are not removed.
						if (pStatObj || !strstr(jointName, "proxy"))
						{
							SetCGASlot(i, pStatObj);

							if (pStatObj && !pDestroyedMaterial)
							{
								if (IMaterial* pMaterial = pStatObj->GetMaterial())
									SetMaterial(pMaterial);
							}

#if ENABLE_VEHICLE_DEBUG
							if (IsDebugParts())
							{
								CryLog("swapping StatObj on joint %u (%s) -> %s", i, jointName, pStatObj ? pStatObj->GetGeoName() : "<NULL>");
							}
#endif
						}
					}
				}

				FlagSkeleton(pSkeletonPose, rIDefaultSkeleton);

				for (TStringVehiclePartMap::iterator ite = m_jointParts.begin(); ite != m_jointParts.end(); ++ite)
				{
					IVehiclePart* pPart = ite->second;
					pPart->ChangeState(state, flags | eVPSF_Physicalize);
				}

				CryCharAnimationParams animParams;
				animParams.m_nFlags |= CA_LOOP_ANIMATION;
				// pSkeleton->SetRedirectToLayer0(1);
				// pSkeleton->StartAnimation("Default",0,  0,0, animParams);  // [MR: commented out on Ivos request]

				if (pDestroyedMaterial)
				{
					SetMaterial(pDestroyedMaterial);
				}
			}
		}
	}
	else if (state == eVGS_Default)
	{
		if (m_pCharInstance && m_pCharInstanceDestroyed)
		{
			// reset material (in case we replaced it with the destroyed material)
			IMaterial* pMaterial = m_pVehicle->GetPaintMaterial();
			if (!pMaterial)
			{
				// no paint, so revert to the material already set on the character
				pMaterial = m_pCharInstance->GetIMaterial();
			}
			if (pMaterial)
			{
				SetMaterial(pMaterial);
			}

			IDefaultSkeleton &rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton();
			{
				for (TStringStatObjMap::iterator ite = m_intactStatObjs.begin(); ite != m_intactStatObjs.end(); ++ite)
				{
					const string &jointName = ite->first;
					IStatObj*     pStatObj  = ite->second;

					int16 jointId = rIDefaultSkeleton.GetJointIDByName(jointName.c_str());
					if (jointId > -1)
					{
						// if compound StatObj (from deformation), use first SubObj for restoring
						if (pStatObj != NULL)
						{
							if (!pStatObj->GetRenderMesh() && pStatObj->GetSubObjectCount() > 0)
							{
								pStatObj = pStatObj->GetSubObject(0)->pStatObj;
							}

							SetCGASlot(jointId, pStatObj);

#if ENABLE_VEHICLE_DEBUG
							if (IsDebugParts())
								CryLog("restoring StatObj on joint %i (%s) -> %s", jointId, jointName.c_str(), pStatObj ? pStatObj->GetGeoName() : "<NULL>");
#endif
						}

						TStringVehiclePartMap::iterator it = m_jointParts.find(jointName);
						if (it != m_jointParts.end())
						{
							it->second->ChangeState(state, flags & ~eVPSF_Physicalize | eVPSF_Force);
						}
					}
				}
				flags |= eVPSF_Physicalize;
			}
		}
	}

	m_state = state;

	// physicalize after all parts have been restored
	if (flags & eVPSF_Physicalize && GetEntity()->GetPhysics())
	{
		Physicalize();
		for (TStringVehiclePartMap::iterator it = m_jointParts.begin(); it != m_jointParts.end(); ++it)
		{
			it->second->Physicalize();
		}
	}

	return true;
}
예제 #2
0
	// TODO: this whole function should be removed and FindHelperObject_Basic integrated back into FindHelperObject.
	//       It manages some undefined cases that appeared in C2, but it should not be needed with a strict definition of how the grabAndThrow helpers have to be defined in the objects
	IStatObj::SSubObject* FindHelperObject_Extended( const char* pHelperName, EntityId objectId, int slot ) 
	{
		IStatObj::SSubObject* pSObjHelper = NULL;
		IEntity* pEntity = gEnv->pEntitySystem->GetEntity( objectId );
		SEntitySlotInfo info;
		if (pEntity && pEntity->GetSlotInfo( slot, info ))
		{
			if (info.pStatObj)  
			{
				IStatObj* pStatObj = info.pStatObj->GetCloneSourceObject(); // we use the clone source in case it exists. Because when it is cloned, only geometries are cloned. the helpers are NOT cloned. 
				if (!pStatObj)
					pStatObj = info.pStatObj;

				// special case: when the pStatObj is the root, we look for the first helper that does not have a hidden parent, whatever is its name as long as it includes pHelperName
				// because: it can be child of a visible geometry (usually "main"...) even when that geometry is not the root
				if (!pSObjHelper && !pStatObj->GetParentObject())
				{
					const int subObjectCount = pStatObj->GetSubObjectCount();
					for (int sid = 0; sid < subObjectCount; ++sid)
					{
						IStatObj::SSubObject* pLocSObjHelper = pStatObj->GetSubObject( sid );
						if ( pLocSObjHelper && (pLocSObjHelper->nType==STATIC_SUB_OBJECT_DUMMY) && strstr( pLocSObjHelper->name.c_str(), pHelperName ))
						{
							pLocSObjHelper = pStatObj->GetSubObject( pLocSObjHelper->nParent );
							if (pLocSObjHelper && (pLocSObjHelper->nType==STATIC_SUB_OBJECT_MESH) && !pLocSObjHelper->bHidden)
							{
								pSObjHelper = pStatObj->GetSubObject( sid );
								break;
							}
						}
					}
				}


				// if all failed, we look from the parent, but by id
				// because: helpers are not necesarily a subobject of their geometry, but just a child 
				if (!pSObjHelper && pStatObj->GetParentObject())
				{
					IStatObj* pParent = pStatObj->GetParentObject();
					IStatObj::SSubObject* pMeSubObject = pParent->FindSubObject( pStatObj->GetGeoName() );
					if (pMeSubObject)
					{
						const int subObjectCount = pParent->GetSubObjectCount();
						for (int sid=0; sid < subObjectCount; ++sid)
						{
							IStatObj::SSubObject* pLocSObjHelper = pParent->GetSubObject( sid );
							if ( pLocSObjHelper && (pLocSObjHelper->nType==STATIC_SUB_OBJECT_DUMMY) && (pLocSObjHelper->name==pHelperName) && (pParent->GetSubObject( pLocSObjHelper->nParent )==pMeSubObject) )
							{
								pSObjHelper = pLocSObjHelper;
								break;
							}
						}
					}
				}

				//If STILL we don't find the object, try with composed name based on geometry name (for destroyed pieces), and look on the whole hierarchy
				if (!pSObjHelper)
				{
					CryFixedStringT<128> helperNameBuffer;
					helperNameBuffer.Format("%s_%s", pStatObj->GetGeoName(), pHelperName);

					pSObjHelper = pStatObj->FindSubObject( helperNameBuffer.c_str() ); 
					if (!pSObjHelper) 
					{
						IStatObj* pObj = pStatObj;
						while (pObj->GetParentObject())   
							pObj = pObj->GetParentObject();
						pSObjHelper = FindHelperObject_RecursivePart( pObj, helperNameBuffer.c_str() );
					}
				}
			}
		}
		return pSObjHelper;
	}