void UEnvQueryTest_Trace::RunTest(FEnvQueryInstance& QueryInstance) const { UObject* DataOwner = QueryInstance.Owner.Get(); BoolValue.BindData(DataOwner, QueryInstance.QueryID); TraceFromContext.BindData(DataOwner, QueryInstance.QueryID); ItemHeightOffset.BindData(DataOwner, QueryInstance.QueryID); ContextHeightOffset.BindData(DataOwner, QueryInstance.QueryID); bool bWantsHit = BoolValue.GetValue(); bool bTraceToItem = TraceFromContext.GetValue(); float ItemZ = ItemHeightOffset.GetValue(); float ContextZ = ContextHeightOffset.GetValue(); TArray<FVector> ContextLocations; if (!QueryInstance.PrepareContext(Context, ContextLocations)) { return; } FCollisionQueryParams TraceParams(TEXT("EnvQueryTrace"), TraceData.bTraceComplex); TraceParams.bTraceAsyncScene = true; TArray<AActor*> IgnoredActors; if (QueryInstance.PrepareContext(Context, IgnoredActors)) { TraceParams.AddIgnoredActors(IgnoredActors); } ECollisionChannel TraceCollisionChannel = UEngineTypes::ConvertToCollisionChannel(TraceData.TraceChannel); FVector TraceExtent(TraceData.ExtentX, TraceData.ExtentY, TraceData.ExtentZ); FRunTraceSignature TraceFunc; switch (TraceData.TraceShape) { case EEnvTraceShape::Line: TraceFunc.BindUObject(this, bTraceToItem ? &UEnvQueryTest_Trace::RunLineTraceTo : &UEnvQueryTest_Trace::RunLineTraceFrom); break; case EEnvTraceShape::Box: TraceFunc.BindUObject(this, bTraceToItem ? &UEnvQueryTest_Trace::RunBoxTraceTo : &UEnvQueryTest_Trace::RunBoxTraceFrom); break; case EEnvTraceShape::Sphere: TraceFunc.BindUObject(this, bTraceToItem ? &UEnvQueryTest_Trace::RunSphereTraceTo : &UEnvQueryTest_Trace::RunSphereTraceFrom); break; case EEnvTraceShape::Capsule: TraceFunc.BindUObject(this, bTraceToItem ? &UEnvQueryTest_Trace::RunCapsuleTraceTo : &UEnvQueryTest_Trace::RunCapsuleTraceFrom); break; default: return; } for (int32 ContextIndex = 0; ContextIndex < ContextLocations.Num(); ContextIndex++) { ContextLocations[ContextIndex].Z += ContextZ; } for (FEnvQueryInstance::ItemIterator It(this, QueryInstance); It; ++It) { const FVector ItemLocation = GetItemLocation(QueryInstance, It.GetIndex()) + FVector(0, 0, ItemZ); AActor* ItemActor = GetItemActor(QueryInstance, It.GetIndex()); for (int32 ContextIndex = 0; ContextIndex < ContextLocations.Num(); ContextIndex++) { const bool bHit = TraceFunc.Execute(ItemLocation, ContextLocations[ContextIndex], ItemActor, QueryInstance.World, TraceCollisionChannel, TraceParams, TraceExtent); It.SetScore(TestPurpose, FilterType, bHit, bWantsHit); } } }
void UEnvQueryGenerator_OnCircle::GenerateItemsForCircle(const FVector& CenterLocation, const FVector& StartDirection, int32 StepsCount, float AngleStep, FEnvQueryInstance& OutQueryInstance) const { TArray<FVector> ItemCandidates; ItemCandidates.AddZeroed(StepsCount); for (int32 Step = 0; Step < StepsCount; ++Step) { ItemCandidates[Step] = CenterLocation + StartDirection.RotateAngleAxis(AngleStep*Step, FVector::UpVector); } #if WITH_RECAST // @todo this needs to be optimize to batch raycasts const ARecastNavMesh* NavMesh = (TraceData.TraceMode == EEnvQueryTrace::Navigation) || (ProjectionData.TraceMode == EEnvQueryTrace::Navigation) ? FEQSHelpers::FindNavMeshForQuery(OutQueryInstance) : NULL; if (NavMesh) { NavMesh->BeginBatchQuery(); } #endif if (TraceData.TraceMode == EEnvQueryTrace::Navigation) { #if WITH_RECAST if (NavMesh != NULL) { TSharedPtr<const FNavigationQueryFilter> NavigationFilter = UNavigationQueryFilter::GetQueryFilter(NavMesh, TraceData.NavigationFilter); TArray<FNavigationRaycastWork> RaycastWorkload; RaycastWorkload.Reserve(ItemCandidates.Num()); for (const auto& ItemLocation : ItemCandidates) { RaycastWorkload.Add(FNavigationRaycastWork(CenterLocation, ItemLocation)); } NavMesh->BatchRaycast(RaycastWorkload, NavigationFilter); for (int32 ItemIndex = 0; ItemIndex < ItemCandidates.Num(); ++ItemIndex) { ItemCandidates[ItemIndex] = RaycastWorkload[ItemIndex].HitLocation.Location; } } #endif } else { ECollisionChannel TraceCollisionChannel = UEngineTypes::ConvertToCollisionChannel(TraceData.TraceChannel); FVector TraceExtent(TraceData.ExtentX, TraceData.ExtentY, TraceData.ExtentZ); FCollisionQueryParams TraceParams(TEXT("EnvQueryTrace"), TraceData.bTraceComplex); TraceParams.bTraceAsyncScene = true; FBatchTracingHelper TracingHelper(OutQueryInstance.World, TraceCollisionChannel, TraceParams, TraceExtent); switch (TraceData.TraceShape) { case EEnvTraceShape::Line: TracingHelper.DoSingleSourceMultiDestinations<EEnvTraceShape::Line>(CenterLocation, ItemCandidates); break; case EEnvTraceShape::Sphere: TracingHelper.DoSingleSourceMultiDestinations<EEnvTraceShape::Sphere>(CenterLocation, ItemCandidates); break; case EEnvTraceShape::Capsule: TracingHelper.DoSingleSourceMultiDestinations<EEnvTraceShape::Capsule>(CenterLocation, ItemCandidates); break; case EEnvTraceShape::Box: TracingHelper.DoSingleSourceMultiDestinations<EEnvTraceShape::Box>(CenterLocation, ItemCandidates); break; default: UE_VLOG(Cast<AActor>(OutQueryInstance.Owner.Get()), LogEQS, Warning, TEXT("UEnvQueryGenerator_OnCircle::CalcDirection failed to calc direction in %s. Using querier facing."), *OutQueryInstance.QueryName); break; } } #if WITH_RECAST if (NavMesh) { ProjectAndFilterNavPoints(ItemCandidates, NavMesh); NavMesh->FinishBatchQuery(); } #endif for (int32 Step = 0; Step < ItemCandidates.Num(); ++Step) { OutQueryInstance.AddItemData<UEnvQueryItemType_Point>(ItemCandidates[Step]); } }