bool APawn::IsBasedOnActor(const AActor* Other) const { UPrimitiveComponent * MovementBase = GetMovementBase(); AActor* MovementBaseActor = MovementBase ? MovementBase->GetOwner() : NULL; if (MovementBaseActor && MovementBaseActor == Other) { return true; } return Super::IsBasedOnActor(Other); }
void ConvertQueryOverlap(const PxShape* PShape, const PxRigidActor* PActor, FOverlapResult& OutOverlap, const PxFilterData& QueryFilter) { const bool bBlock = IsBlocking(PShape, QueryFilter); FBodyInstance* BodyInst = FPhysxUserData::Get<FBodyInstance>(PActor->userData); FDestructibleChunkInfo* ChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(PActor->userData); // Grab actor/component UPrimitiveComponent* OwnerComponent = nullptr; // Try body instance if (BodyInst) { OwnerComponent = BodyInst->OwnerComponent.Get(); // cache weak pointer object, avoid multiple derefs below. if (OwnerComponent) { OutOverlap.Actor = OwnerComponent->GetOwner(); OutOverlap.Component = BodyInst->OwnerComponent; // Copying weak pointer is faster than assigning raw pointer. OutOverlap.ItemIndex = OwnerComponent->bMultiBodyOverlap ? BodyInst->InstanceBodyIndex : INDEX_NONE; } } if (!OwnerComponent) { // Try chunk info if (ChunkInfo) { OwnerComponent = ChunkInfo->OwningComponent.Get(); // cache weak pointer object, avoid multiple derefs below. if (OwnerComponent) { OutOverlap.Actor = OwnerComponent->GetOwner(); OutOverlap.Component = ChunkInfo->OwningComponent; // Copying weak pointer is faster than assigning raw pointer. OutOverlap.ItemIndex = OwnerComponent->bMultiBodyOverlap ? UDestructibleComponent::ChunkIdxToBoneIdx(ChunkInfo->ChunkIndex) : INDEX_NONE; } } } // Other info OutOverlap.bBlockingHit = bBlock; }
ALODActor* FHierarchicalLODUtilities::GetParentLODActor(const AActor* InActor) { ALODActor* ParentActor = nullptr; if (InActor) { TArray<UStaticMeshComponent*> ComponentArray; InActor->GetComponents<UStaticMeshComponent>(ComponentArray); for (auto Component : ComponentArray) { UPrimitiveComponent* ParentComponent = Component->GetLODParentPrimitive(); if (ParentComponent) { ParentActor = CastChecked<ALODActor>(ParentComponent->GetOwner()); break; } } } return ParentActor; }
bool FPhysicsManipulationEdMode::StartTracking( FEditorViewportClient* InViewportClient, FViewport* InViewport ) { //UE_LOG(LogEditorPhysMode, Warning, TEXT("Start Tracking")); FVector GrabLocation(0,0,0); UPrimitiveComponent* ComponentToGrab = NULL; USelection* Selection = GEditor->GetSelectedActors(); for (int32 i=0; i<Selection->Num(); ++i) { AActor* SelectedActor = Cast<AActor>(Selection->GetSelectedObject(i)); if (SelectedActor != NULL) { UPrimitiveComponent* PC = Cast<UPrimitiveComponent>(SelectedActor->GetRootComponent()); if (PC != NULL && PC->BodyInstance.bSimulatePhysics) { ComponentToGrab = PC; HandleTargetLocation = SelectedActor->GetActorLocation(); HandleTargetRotation = SelectedActor->GetActorRotation(); break; } if (ComponentToGrab != NULL) { break; } } } if (ComponentToGrab != NULL) { HandleComp->GrabComponent(ComponentToGrab, NAME_None, ComponentToGrab->GetOwner()->GetActorLocation(), true); } return FEdMode::StartTracking(InViewportClient, InViewport); }
bool APawn::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const { CA_SUPPRESS(6011); if (bAlwaysRelevant || RealViewer == Controller || IsOwnedBy(ViewTarget) || IsOwnedBy(RealViewer) || this == ViewTarget || ViewTarget == Instigator || IsBasedOnActor(ViewTarget) || (ViewTarget && ViewTarget->IsBasedOnActor(this))) { return true; } else if( (bHidden || bOnlyRelevantToOwner) && (!GetRootComponent() || !GetRootComponent()->IsCollisionEnabled()) ) { return false; } else { UPrimitiveComponent* MovementBase = GetMovementBase(); AActor* BaseActor = MovementBase ? MovementBase->GetOwner() : NULL; if ( MovementBase && BaseActor && GetMovementComponent() && ((Cast<const USkeletalMeshComponent>(MovementBase)) || (BaseActor == GetOwner())) ) { return BaseActor->IsNetRelevantFor(RealViewer, ViewTarget, SrcLocation); } } return ((SrcLocation - GetActorLocation()).SizeSquared() < NetCullDistanceSquared); }
FVector AAIController::GetFocalPoint() { FBasedPosition FinalFocus; // find focus with highest priority for( int32 Index = FocusInformation.Priorities.Num()-1; Index >= 0; --Index) { const FFocusKnowledge::FFocusItem& Focusitem = FocusInformation.Priorities[Index]; if ( Focusitem.Actor.IsValid() ) { const AActor* Focus = Focusitem.Actor.Get(); UPrimitiveComponent* MyBase = GetPawn() ? GetPawn()->GetMovementBase() : NULL; const bool bRequestedFocusIsBased = MyBase && Cast<const APawn>(Focus) && (Cast<const APawn>(Focus)->GetMovementBase() == MyBase); FinalFocus.Set(bRequestedFocusIsBased && MyBase ? MyBase->GetOwner() : NULL, Focus->GetActorLocation()); break; } else if( !(*Focusitem.Position).IsZero() ) { FinalFocus = Focusitem.Position; break; } } return *FinalFocus; }
/** Set info in the HitResult (Actor, Component, PhysMaterial, BoneName, Item) based on the supplied shape and face index */ static void SetHitResultFromShapeAndFaceIndex(const PxShape* PShape, const PxRigidActor* PActor, const uint32 FaceIndex, FHitResult& OutResult, bool bReturnPhysMat) { const FBodyInstance* BodyInst = FPhysxUserData::Get<FBodyInstance>(PActor->userData); FDestructibleChunkInfo* ChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(PShape->userData); UPrimitiveComponent* PrimComp = FPhysxUserData::Get<UPrimitiveComponent>(PShape->userData); if(BodyInst) { BodyInst = BodyInst->GetOriginalBodyInstance(PShape); } if (ChunkInfo == NULL) { ChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(PActor->userData); } UPrimitiveComponent* OwningComponent = ChunkInfo != NULL ? ChunkInfo->OwningComponent.Get() : NULL; if (OwningComponent == NULL && BodyInst != NULL) { OwningComponent = BodyInst->OwnerComponent.Get(); } // If the shape has a different parent component, we take that one instead of the ChunkInfo. This can happen in some // cases where APEX moves shapes internally to another actor ( ex. FormExtended structures ) if (PrimComp != NULL && OwningComponent != PrimComp) { OwningComponent = PrimComp; } OutResult.PhysMaterial = NULL; bool bReturnBody = false; // Grab actor/component if( OwningComponent ) { OutResult.Actor = OwningComponent->GetOwner(); OutResult.Component = OwningComponent; if (bReturnPhysMat) { // This function returns the single material in all cases other than trimesh or heightfield if(PxMaterial* PxMat = PShape->getMaterialFromInternalFaceIndex(FaceIndex)) { OutResult.PhysMaterial = FPhysxUserData::Get<UPhysicalMaterial>(PxMat->userData); } } bReturnBody = OwningComponent->bMultiBodyOverlap; } // For destructibles give the ChunkInfo-Index as Item if (bReturnBody && ChunkInfo) { OutResult.Item = ChunkInfo->ChunkIndex; UDestructibleComponent* DMComp = Cast<UDestructibleComponent>(OwningComponent); OutResult.BoneName = DMComp->GetBoneName(UDestructibleComponent::ChunkIdxToBoneIdx(ChunkInfo->ChunkIndex)); } // If BodyInstance and not destructible, give BodyIndex as Item else if (BodyInst) { OutResult.Item = BodyInst->InstanceBodyIndex; const UBodySetup* BodySetup = BodyInst->BodySetup.Get(); if (BodySetup) { OutResult.BoneName = BodySetup->BoneName; } } else { // invalid index OutResult.Item = INDEX_NONE; OutResult.BoneName = NAME_None; } OutResult.FaceIndex = INDEX_NONE; }
void UGripMotionControllerComponent::TickGrip() { if (GrippedActors.Num()) { FTransform WorldTransform; FTransform InverseTransform = this->GetComponentTransform().Inverse(); for (int i = GrippedActors.Num() - 1; i >= 0; --i) { if (GrippedActors[i].Actor || GrippedActors[i].Component) { // GetRelativeTransformReverse had some serious f*****g floating point errors associated with it that was f*****g everything up // Not sure whats wrong with the function but I might want to push a patch out eventually WorldTransform = GrippedActors[i].RelativeTransform.GetRelativeTransform(InverseTransform); UPrimitiveComponent *root = GrippedActors[i].Component; AActor *actor = GrippedActors[i].Actor; if (!root) root = Cast<UPrimitiveComponent>(GrippedActors[i].Actor->GetRootComponent()); if (!root) continue; if (!actor) actor = root->GetOwner(); if (!actor) continue; if (bIsServer) { // Handle collision intersection detection, this is used to intelligently manage some of the networking and late update features. switch (GrippedActors[i].GripCollisionType.GetValue()) { case EGripCollisionType::InteractiveCollisionWithPhysics: case EGripCollisionType::InteractiveHybridCollisionWithSweep: { TArray<FOverlapResult> Hits; FComponentQueryParams Params(NAME_None, this->GetOwner()); Params.bTraceAsyncScene = root->bCheckAsyncSceneOnMove; Params.AddIgnoredActor(actor); Params.AddIgnoredActors(root->MoveIgnoreActors); if(GetWorld()->ComponentOverlapMulti(Hits, root, root->GetComponentLocation(), root->GetComponentQuat(), Params)) { GrippedActors[i].bColliding = true; } else { GrippedActors[i].bColliding = false; } } // Skip collision intersects with these types, they dont need it case EGripCollisionType::PhysicsOnly: case EGripCollisionType::SweepWithPhysics: case EGripCollisionType::InteractiveCollisionWithSweep: default:break; } } // Need to figure out best default behavior /*if (GrippedActors[i].bHasSecondaryAttachment && GrippedActors[i].SecondaryAttachment) { WorldTransform.SetRotation((WorldTransform.GetLocation() - GrippedActors[i].SecondaryAttachment->GetComponentLocation()).ToOrientationRotator().Quaternion()); }*/ if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveCollisionWithPhysics) { UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform); } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveCollisionWithSweep) { if (bIsServer) { FHitResult OutHit; // Need to use without teleport so that the physics velocity is updated for when the actor is released to throw root->SetWorldTransform(WorldTransform, true, &OutHit); if (OutHit.bBlockingHit) { GrippedActors[i].bColliding = true; if (!actor->bReplicateMovement) actor->SetReplicateMovement(true); } else { GrippedActors[i].bColliding = false; if (actor->bReplicateMovement) actor->SetReplicateMovement(false); } } else { if (!GrippedActors[i].bColliding) { root->SetWorldTransform(WorldTransform, true); } } } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveHybridCollisionWithSweep) { // Need to use without teleport so that the physics velocity is updated for when the actor is released to throw //if (bIsServer) //{ FBPActorPhysicsHandleInformation * GripHandle = GetPhysicsGrip(GrippedActors[i]); if (!GrippedActors[i].bColliding) { // Make sure that there is no collision on course before turning off collision and snapping to controller if (bIsServer && actor && actor->bReplicateMovement) { FCollisionQueryParams QueryParams(NAME_None, false, this->GetOwner()); FCollisionResponseParams ResponseParam; root->InitSweepCollisionParams(QueryParams, ResponseParam); QueryParams.AddIgnoredActor(actor); QueryParams.AddIgnoredActors(root->MoveIgnoreActors); if (GetWorld()->SweepTestByChannel(root->GetComponentLocation(), WorldTransform.GetLocation(), root->GetComponentQuat(), ECollisionChannel::ECC_Visibility, root->GetCollisionShape(), QueryParams, ResponseParam)) { GrippedActors[i].bColliding = true; } else { GrippedActors[i].bColliding = false; } } // If still not colliding if (!GrippedActors[i].bColliding) { if (bIsServer && actor->bReplicateMovement) // So we don't call on on change event over and over locally actor->SetReplicateMovement(false); if (bIsServer && GripHandle) { DestroyPhysicsHandle(GrippedActors[i]); if(GrippedActors[i].Actor) GrippedActors[i].Actor->DisableComponentsSimulatePhysics(); else root->SetSimulatePhysics(false); } root->SetWorldTransform(WorldTransform, false); } else { if (bIsServer && GrippedActors[i].bColliding && GripHandle) UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform); } } else if (GrippedActors[i].bColliding && !GripHandle) { if (bIsServer && !actor->bReplicateMovement) actor->SetReplicateMovement(true); root->SetSimulatePhysics(true); if (bIsServer) SetUpPhysicsHandle(GrippedActors[i]); } else { if (bIsServer && GrippedActors[i].bColliding && GripHandle) UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform); } } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::SweepWithPhysics) { if (bIsServer) { FVector OriginalPosition(root->GetComponentLocation()); FRotator OriginalOrientation(root->GetComponentRotation()); FVector NewPosition(WorldTransform.GetTranslation()); FRotator NewOrientation(WorldTransform.GetRotation()); // Now sweep collision separately so we can get hits but not have the location altered if (bUseWithoutTracking || NewPosition != OriginalPosition || NewOrientation != OriginalOrientation) { FVector move = NewPosition - OriginalPosition; // ComponentSweepMulti does nothing if moving < KINDA_SMALL_NUMBER in distance, so it's important to not try to sweep distances smaller than that. const float MinMovementDistSq = (FMath::Square(4.f*KINDA_SMALL_NUMBER)); if (bUseWithoutTracking || move.SizeSquared() > MinMovementDistSq || NewOrientation != OriginalOrientation) { if (CheckComponentWithSweep(root, move, NewOrientation, false)) { } } } // Move the actor, we are not offsetting by the hit result anyway root->SetWorldTransform(WorldTransform, false); } else { // Move the actor, we are not offsetting by the hit result anyway root->SetWorldTransform(WorldTransform, false); } } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::PhysicsOnly) { // Move the actor, we are not offsetting by the hit result anyway root->SetWorldTransform(WorldTransform, false); } } else { if (bIsServer) { DestroyPhysicsHandle(GrippedActors[i]); GrippedActors.RemoveAt(i); // If it got garbage collected then just remove the pointer, won't happen with new uproperty use, but keeping it here anyway } } } } }
void UGripMotionControllerComponent::NotifyGrip_Implementation(const FBPActorGripInformation &NewGrip) { switch (NewGrip.GripCollisionType.GetValue()) { case EGripCollisionType::InteractiveCollisionWithPhysics: { if (bIsServer) { if (NewGrip.Component && NewGrip.Component->GetOwner()) NewGrip.Component->GetOwner()->SetReplicateMovement(false); else if (NewGrip.Actor) NewGrip.Actor->SetReplicateMovement(false); } SetUpPhysicsHandle(NewGrip); } break; // Skip collision intersects with these types, they dont need it case EGripCollisionType::PhysicsOnly: case EGripCollisionType::SweepWithPhysics: case EGripCollisionType::InteractiveHybridCollisionWithSweep: case EGripCollisionType::InteractiveCollisionWithSweep: default: { if (NewGrip.Component) NewGrip.Component->SetSimulatePhysics(false); else if(NewGrip.Actor) NewGrip.Actor->DisableComponentsSimulatePhysics(); if (bIsServer) { if (NewGrip.Component && NewGrip.Component->GetOwner()) NewGrip.Component->GetOwner()->SetReplicateMovement(false); else if(NewGrip.Actor) NewGrip.Actor->SetReplicateMovement(false); } } break; } UPrimitiveComponent *root = NewGrip.Component; if (!root && NewGrip.Actor) { root = Cast<UPrimitiveComponent>(NewGrip.Actor->GetRootComponent()); if (root) root->SetEnableGravity(false); this->IgnoreActorWhenMoving(NewGrip.Actor, true); } else if (root) { root->SetEnableGravity(false); if(root->GetOwner()) this->IgnoreActorWhenMoving(root->GetOwner(), true); } }
bool UGripMotionControllerComponent::CheckComponentWithSweep(UPrimitiveComponent * ComponentToCheck, FVector Move, FRotator newOrientation, bool bSkipSimulatingComponents/*, bool &bHadBlockingHitOut*/) { TArray<FHitResult> Hits; // WARNING: HitResult is only partially initialized in some paths. All data is valid only if bFilledHitResult is true. FHitResult BlockingHit(NoInit); BlockingHit.bBlockingHit = false; BlockingHit.Time = 1.f; bool bFilledHitResult = false; bool bMoved = false; bool bIncludesOverlapsAtEnd = false; bool bRotationOnly = false; UPrimitiveComponent *root = ComponentToCheck; if (!root || !root->IsQueryCollisionEnabled()) return false; FVector start(root->GetComponentLocation()); const bool bCollisionEnabled = root->IsQueryCollisionEnabled(); if (bCollisionEnabled) { #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (!root->IsRegistered()) { UE_LOG(LogTemp, Warning, TEXT("MovedComponent %s not initialized in grip motion controller"), *root->GetFullName()); } #endif UWorld* const MyWorld = GetWorld(); FComponentQueryParams Params(TEXT("sweep_params"), root->GetOwner()); FCollisionResponseParams ResponseParam; root->InitSweepCollisionParams(Params, ResponseParam); bool const bHadBlockingHit = MyWorld->ComponentSweepMulti(Hits, root, start, start + Move, newOrientation, Params); if (bHadBlockingHit) { int32 BlockingHitIndex = INDEX_NONE; float BlockingHitNormalDotDelta = BIG_NUMBER; for (int32 HitIdx = 0; HitIdx < Hits.Num(); HitIdx++) { const FHitResult& TestHit = Hits[HitIdx]; // Ignore the owning actor to the motion controller if (TestHit.Actor == this->GetOwner() || (bSkipSimulatingComponents && TestHit.Component->IsSimulatingPhysics())) { if (Hits.Num() == 1) { //bHadBlockingHitOut = false; return false; } else continue; } if (TestHit.bBlockingHit && TestHit.IsValidBlockingHit()) { if (TestHit.Time == 0.f) { // We may have multiple initial hits, and want to choose the one with the normal most opposed to our movement. const float NormalDotDelta = (TestHit.ImpactNormal | Move); if (NormalDotDelta < BlockingHitNormalDotDelta) { BlockingHitNormalDotDelta = NormalDotDelta; BlockingHitIndex = HitIdx; } } else if (BlockingHitIndex == INDEX_NONE) { // First non-overlapping blocking hit should be used, if an overlapping hit was not. // This should be the only non-overlapping blocking hit, and last in the results. BlockingHitIndex = HitIdx; break; } //} } } // Update blocking hit, if there was a valid one. if (BlockingHitIndex >= 0) { BlockingHit = Hits[BlockingHitIndex]; bFilledHitResult = true; } } } // Handle blocking hit notifications. Avoid if pending kill (which could happen after overlaps). if (BlockingHit.bBlockingHit && !root->IsPendingKill()) { check(bFilledHitResult); if (root->IsDeferringMovementUpdates()) { FScopedMovementUpdate* ScopedUpdate = root->GetCurrentScopedMovement(); ScopedUpdate->AppendBlockingHitAfterMove(BlockingHit); } else { if(root->GetOwner()) root->DispatchBlockingHit(*root->GetOwner(), BlockingHit); } return true; } return false; }
void FGameplayDebuggerCategory_AI::CollectData(APlayerController* OwnerPC, AActor* DebugActor) { APawn* MyPawn = Cast<APawn>(DebugActor); ACharacter* MyChar = Cast<ACharacter>(MyPawn); DataPack.PawnName = MyPawn ? MyPawn->GetHumanReadableName() : FString(TEXT("{red}No selected pawn.")); DataPack.bIsUsingCharacter = (MyChar != nullptr); AAIController* MyController = MyPawn ? Cast<AAIController>(MyPawn->Controller) : nullptr; DataPack.bHasController = (MyController != nullptr); if (MyController) { if (MyController->IsPendingKill() == false) { DataPack.ControllerName = MyController->GetName(); } else { DataPack.ControllerName = TEXT("Controller PENDING KILL"); } } else { DataPack.ControllerName = TEXT("No Controller"); } if (MyPawn && !MyPawn->IsPendingKill()) { UCharacterMovementComponent* CharMovementComp = MyChar ? MyChar->GetCharacterMovement() : nullptr; if (CharMovementComp) { UPrimitiveComponent* FloorComponent = MyPawn->GetMovementBase(); AActor* FloorActor = FloorComponent ? FloorComponent->GetOwner() : nullptr; DataPack.MovementBaseInfo = FloorComponent ? FString::Printf(TEXT("%s.%s"), *GetNameSafe(FloorActor), *FloorComponent->GetName()) : FString(TEXT("None")); DataPack.MovementModeInfo = CharMovementComp->GetMovementName(); } UBehaviorTreeComponent* BehaviorComp = MyController ? Cast<UBehaviorTreeComponent>(MyController->BrainComponent) : nullptr; DataPack.bIsUsingBehaviorTree = (BehaviorComp != nullptr); if (BehaviorComp) { DataPack.CurrentAITask = BehaviorComp->DescribeActiveTasks(); DataPack.CurrentAIState = BehaviorComp->IsRunning() ? TEXT("Running") : BehaviorComp->IsPaused() ? TEXT("Paused") : TEXT("Inactive"); DataPack.CurrentAIAssets = BehaviorComp->DescribeActiveTrees(); } UGameplayTasksComponent* TasksComponent = MyController ? MyController->GetGameplayTasksComponent() : nullptr; DataPack.bIsUsingGameplayTasks = (TasksComponent != nullptr); if (TasksComponent) { for (FConstGameplayTaskIterator It = TasksComponent->GetTickingTaskIterator(); It; ++It) { const UGameplayTask* TaskOb = *It; if (TaskOb) { DataPack.TickingTaskInfo += DescribeTaskHelper(*TaskOb); DataPack.NumTickingTasks++; } } for (FConstGameplayTaskIterator It = TasksComponent->GetPriorityQueueIterator(); It; ++It) { const UGameplayTask* TaskOb = *It; if (TaskOb) { DataPack.TaskQueueInfo += DescribeTaskHelper(*TaskOb); DataPack.NumTasksInQueue++; } } } DataPack.MontageInfo = MyChar ? GetNameSafe(MyChar->GetCurrentMontage()) : FString(); UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(MyPawn->GetWorld()); const ANavigationData* NavData = MyController && NavSys ? NavSys->GetNavDataForProps(MyController->GetNavAgentPropertiesRef()) : nullptr; DataPack.NavDataInfo = NavData ? NavData->GetConfig().Name.ToString() : FString(); CollectPathData(MyController); } else { PathDataPack.PathCorridor.Reset(); PathDataPack.PathPoints.Reset(); } }