void DumpSkeleton(IDefaultSkeleton &rIDefaultSkeleton)
{
	for (int i = 0; i < rIDefaultSkeleton.GetJointCount(); ++i)
	{
		const char* name     = rIDefaultSkeleton.GetJointNameByID(i);
		int         parentid = rIDefaultSkeleton.GetJointParentIDByID(i);

		if (parentid != -1)
			CryLog("joint %i: %s (parent %i)", i, name, parentid);
		else
			CryLog("joint %i: %s", i, name);
	}
}
Exemple #2
0
bool CLookAtSimple::ValidateJointId(IDefaultSkeleton& rIDefaultSkeleton)
{
	if (m_stateExecute.jointId < 0)
		return false;
	return m_stateExecute.jointId < rIDefaultSkeleton.GetJointCount();
}
//------------------------------------------------------------------------
void CVehiclePartAnimated::FlagSkeleton(ISkeletonPose* pSkeletonPose,IDefaultSkeleton &rIDefaultSkeleton)
{
	if (!pSkeletonPose)
		return;

	IPhysicalEntity* pPhysics = GetEntity()->GetPhysics();
	if (!pPhysics)
		return;

	string name;
	int    idWater       = rIDefaultSkeleton.GetJointIDByName("proxy_water");
	uint32 buoyancyParts = (idWater != -1) ? 1 : 0;

	uint32 jointCount = rIDefaultSkeleton.GetJointCount();
	for (uint32 i = 0; i < jointCount; ++i)
	{
		int physId = pSkeletonPose->GetPhysIdOnJoint(i);

		if (physId >= 0)
		{
			CheckColltypeHeavy(physId);
			name = rIDefaultSkeleton.GetJointNameByID(i);

			// when water proxy available, remove float from all others
			// if no water proxy, we leave only "proxy" parts floating
			if (idWater != -1)
			{
				if (i == idWater)
				{
					SetFlags(physId, geom_collides, false);
					SetFlagsCollider(physId, 0);
				}
				else
					SetFlags(physId, geom_floats, false);
			}
			else
			{
				if (name.find("proxy") != string::npos)
					++buoyancyParts;
				else
					SetFlags(physId, geom_floats, false);
			}

			// all objects which have a corresponding *_proxy on the skeleton
			// are set to ray collision only
			if (name.find("_proxy") == string::npos)
			{
				name.append("_proxy");
				int proxyId = rIDefaultSkeleton.GetJointIDByName(name.c_str());

				if (proxyId != -1)
				{
					// remove ray collision from hull proxy(s)
					SetFlags(pSkeletonPose->GetPhysIdOnJoint(proxyId), geom_colltype_ray | geom_colltype13, false);

					// get StatObj from main part, to connect proxies foreignData with it
					IStatObj* pStatObj = pSkeletonPose->GetStatObjOnJoint(i);

					if (pStatObj)
					{
						pe_params_part params;
						params.partid = proxyId;
						if (pPhysics->GetParams(&params))
						{
							if (params.pPhysGeom && params.pPhysGeom->pGeom)
								params.pPhysGeom->pGeom->SetForeignData(pStatObj, 0);
						}
					}

					for (int p = 2; p < 6; ++p)
					{
						// check additional proxies, by naming convention _02, .. _05
						char buf[64];
						cry_sprintf(buf, "%s_%02i", name.c_str(), p);

						proxyId = rIDefaultSkeleton.GetJointIDByName(buf);
						if (proxyId == -1)
							break;

						int proxyPhysId = pSkeletonPose->GetPhysIdOnJoint(proxyId);
						if (proxyPhysId == -1)
							continue;

						SetFlags(proxyPhysId, geom_colltype_ray | geom_colltype13, false);

						// connect proxies to main StatObj (needed for bullet tests, decals)
						if (pStatObj)
						{
							pe_params_part params;
							params.partid = proxyPhysId;
							if (pPhysics->GetParams(&params))
							{
								if (params.pPhysGeom && params.pPhysGeom->pGeom)
									params.pPhysGeom->pGeom->SetForeignData(pStatObj, 0);
							}
						}
					}

					// set ray-collision only on the part
					SetFlags(physId, geom_collides | geom_floats, false);
					SetFlags(physId, geom_colltype_ray | geom_colltype13, true);
					SetFlagsCollider(physId, 0);
				}
			}
		}
	}

	if (buoyancyParts == 0)
	{
		// as fallback, use part with largest volume for buoyancy
		int   partId = -1;
		float maxV   = 0.f;

		pe_status_nparts nparts;
		int              numParts = pPhysics->GetStatus(&nparts);

		for (int i = 0; i < numParts; ++i)
		{
			pe_params_part params;
			params.ipart = i;
			if (pPhysics->GetParams(&params))
			{
				float v = (params.pPhysGeomProxy) ? params.pPhysGeomProxy->V : params.pPhysGeom->V;
				if (v > maxV)
				{
					partId = params.partid;
					maxV   = v;
				}
			}
		}

		if (partId != -1)
			SetFlags(partId, geom_floats, true);
		else
			GameWarning("[CVehiclePartAnimated]: <%s> has no buoyancy parts! (Check material for correct physicalization setup properties)",GetEntity()->GetName());
	}

	int jointId, physId;
	if ((jointId = rIDefaultSkeleton.GetJointIDByName("proxy_skirt")) != -1)
	{
		if ((physId = pSkeletonPose->GetPhysIdOnJoint(jointId)) != -1)
		{
			SetFlags(physId, geom_collides | geom_floats, false);
			SetFlags(physId, geom_colltype_ray | geom_colltype13 | geom_colltype_player | geom_colltype_foliage, true);
			SetFlagsCollider(physId, 0);
		}
	}

	// remove collision flags from all _proxy geoms by debug cvar
	// useful for seeing through, testing ray proxies etc
	if (VehicleCVars().v_disable_hull > 0)
	{
		for (uint32 i = 0; i < rIDefaultSkeleton.GetJointCount(); ++i)
		{
			if (strstr(rIDefaultSkeleton.GetJointNameByID(i), "_proxy"))
			{
				SetFlags(pSkeletonPose->GetPhysIdOnJoint(i), geom_collides | geom_floats, false);
				SetFlagsCollider(pSkeletonPose->GetPhysIdOnJoint(i), 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;
}