FActorPositionTraceResult FActorPositioning::TraceWorldForPosition(const UWorld& InWorld, const FSceneView& InSceneView, const FVector& RayStart, const FVector& RayEnd, const TArray<AActor*>* IgnoreActors) { TArray<FHitResult> Hits; FCollisionQueryParams Param(TEXT("DragDropTrace"), true); Param.bTraceAsyncScene = true; if (IgnoreActors) { Param.AddIgnoredActors(*IgnoreActors); } FActorPositionTraceResult Results; if ( InWorld.LineTraceMultiByObjectType(Hits, RayStart, RayEnd, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllObjects), Param) ) { { // Filter out anything that should be ignored FSuspendRenderingThread SuspendRendering(false); Hits.RemoveAll([&](const FHitResult& Hit){ return IsHitIgnored(Hit, InSceneView); }); } // Go through all hits and find closest float ClosestHitDistanceSqr = TNumericLimits<float>::Max(); for (const auto& Hit : Hits) { const float DistanceToHitSqr = (Hit.ImpactPoint - RayStart).SizeSquared(); if (DistanceToHitSqr < ClosestHitDistanceSqr) { ClosestHitDistanceSqr = DistanceToHitSqr; Results.Location = Hit.Location; Results.SurfaceNormal = Hit.Normal.GetSafeNormal(); Results.State = FActorPositionTraceResult::HitSuccess; Results.HitActor = Hit.Actor; } } } return Results; }
/** * Constructor that flushes and suspends the renderthread * @param bRecreateThread - Whether the rendering thread should be completely destroyed and recreated, or just suspended. */ FSuspendRenderingThread::FSuspendRenderingThread( bool bInRecreateThread ) { bRecreateThread = bInRecreateThread; bUseRenderingThread = GUseThreadedRendering; bWasRenderingThreadRunning = GIsThreadedRendering; if ( bRecreateThread ) { GUseThreadedRendering = false; StopRenderingThread(); FPlatformAtomics::InterlockedIncrement( &GIsRenderingThreadSuspended ); } else { if ( GIsRenderingThreadSuspended == 0 ) { // First tell the render thread to finish up all pending commands and then suspend its activities. // this ensures that async stuff will be completed too FlushRenderingCommands(); if (GIsThreadedRendering) { DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.SuspendRendering"), STAT_FSimpleDelegateGraphTask_SuspendRendering, STATGROUP_TaskGraphTasks); FGraphEventRef CompleteHandle = FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateStatic(&SuspendRendering), GET_STATID(STAT_FSimpleDelegateGraphTask_SuspendRendering), NULL, ENamedThreads::RenderThread); // Busy wait while Kismet debugging, to avoid opportunistic execution of game thread tasks // If the game thread is already executing tasks, then we have no choice but to spin if (GIntraFrameDebuggingGameThread || FTaskGraphInterface::Get().IsThreadProcessingTasks(ENamedThreads::GameThread) ) { while (!GIsRenderingThreadSuspended) { FPlatformProcess::Sleep(0.0f); } } else { FTaskGraphInterface::Get().WaitUntilTaskCompletes(CompleteHandle, ENamedThreads::GameThread); } check(GIsRenderingThreadSuspended); // Now tell the render thread to busy wait until it's resumed DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.WaitAndResumeRendering"), STAT_FSimpleDelegateGraphTask_WaitAndResumeRendering, STATGROUP_TaskGraphTasks); FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateStatic(&WaitAndResumeRendering), GET_STATID(STAT_FSimpleDelegateGraphTask_WaitAndResumeRendering), NULL, ENamedThreads::RenderThread); } else { SuspendRendering(); } } else { // The render-thread is already suspended. Just bump the ref-count. FPlatformAtomics::InterlockedIncrement( &GIsRenderingThreadSuspended ); } } }