void UDestructibleComponent::SetCollisionResponseForAllActors(const FCollisionResponseContainer& ResponseOverride) { #if WITH_APEX if (ApexDestructibleActor == NULL) { return; } PxRigidDynamic** PActorBuffer = NULL; PxU32 PActorCount = 0; if (ApexDestructibleActor->acquirePhysXActorBuffer(PActorBuffer, PActorCount)) { PxScene* LockedScene = NULL; while (PActorCount--) { PxRigidDynamic* PActor = *PActorBuffer++; if (PActor != NULL) { FDestructibleChunkInfo* ChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(PActor->userData); if (ChunkInfo != NULL) { if (!LockedScene) { LockedScene = PActor->getScene(); LockedScene->lockWrite(); LockedScene->lockRead(); } SetCollisionResponseForActor(PActor, ChunkInfo->ChunkIndex, &ResponseOverride); // ChunkIndex is the last chunk made visible. But SetCollisionResponseForActor already doesn't respect per-chunk collision properties. } } } if (LockedScene) { LockedScene->unlockRead(); LockedScene->unlockWrite(); LockedScene = NULL; } ApexDestructibleActor->releasePhysXActorBuffer(); } #endif }
void UDestructibleComponent::SetChunkVisible( int32 ChunkIndex, bool bVisible ) { // Bone 0 is a dummy root bone const int32 BoneIndex = ChunkIdxToBoneIdx(ChunkIndex); bool bClearActorFromChunkInfo = false; if( bVisible ) { UnHideBone(BoneIndex); #if WITH_APEX PxRigidDynamic* PActor = ApexDestructibleActor != NULL ? ApexDestructibleActor->getChunkPhysXActor(ChunkIndex) : NULL; UDestructibleMesh* DMesh = GetDestructibleMesh(); if (PActor != NULL) { // If actor has already a chunk info and userdata, we just make sure it is valid and update the // physx actor if needed. We do NOT do this for FormExtended structures, as in this case, the shapes/actors // are moved to the 1st structure object internally by APEX. if(PActor->userData != NULL && !DMesh->DefaultDestructibleParameters.Flags.bFormExtendedStructures) { FDestructibleChunkInfo* CI = FPhysxUserData::Get<FDestructibleChunkInfo>(PActor->userData); checkf(CI, TEXT("If a chunk actor has user data and it is not a DestructibleChunkInfo, something is messed up.")); //check(CI->OwningComponent == this); if (CI->ChunkIndex != ChunkIndex) { // grab the old actor and clear its user data, as we steal the ChunkInfo here if (CI->Actor && CI->Actor != PActor) { CI->Actor->userData = NULL; } CI->ChunkIndex = ChunkIndex; } CI->OwningComponent = this; CI->Actor = PActor; } else if (PActor->userData == NULL) { // Setup the user data to have a proper chunk - actor mapping int32 InfoIndex = ChunkInfos.AddUninitialized(); FDestructibleChunkInfo* CI = &ChunkInfos[InfoIndex]; CI->Index = InfoIndex; CI->ChunkIndex = ChunkIndex; CI->OwningComponent = this; CI->Actor = PActor; int32 UserDataIdx = PhysxChunkUserData.Add(FPhysxUserData(CI)); check(InfoIndex == UserDataIdx); PActor->userData = &PhysxChunkUserData[UserDataIdx]; // Set collision response to non-root chunks if (GetDestructibleMesh()->ApexDestructibleAsset->getChunkParentIndex(ChunkIndex) >= 0) { SetCollisionResponseForActor(ChunkCollisionResponse, PActor, ChunkIndex); } } } else { bClearActorFromChunkInfo = true; } #endif // WITH_APEX } else { HideBone(BoneIndex, PBO_None); bClearActorFromChunkInfo = true; } #if WITH_APEX if (bClearActorFromChunkInfo) { // Make sure we clear the physx actor pointer of the chunk info as it might (and probably will) be // invalid from now on for (int32 i=0; i < ChunkInfos.Num(); ++i) { if (ChunkInfos[i].ChunkIndex == ChunkIndex) { ChunkInfos[i].Actor = NULL; break; } } } #endif // WITH_APEX // Mark the transform as dirty, so the bounds are updated and sent to the render thread MarkRenderTransformDirty(); // New bone positions need to be sent to render thread MarkRenderDynamicDataDirty(); }