FVector ExtractLocation(TSubclassOf<UEnvQueryItemType> ItemType, const TArray<uint8>& RawData, const TArray<FEnvQueryItem>& Items, int32 Index) { if (Items.IsValidIndex(Index) && ItemType->IsChildOf(UEnvQueryItemType_VectorBase::StaticClass())) { UEnvQueryItemType_VectorBase* DefTypeOb = ItemType->GetDefaultObject<UEnvQueryItemType_VectorBase>(); return DefTypeOb->GetItemLocation(RawData.GetData() + Items[Index].DataOffset); } return FVector::ZeroVector; }
FVector FEnvQueryResult::GetItemAsLocation(int32 Index) const { if (Items.IsValidIndex(Index) && ItemType->IsChildOf(UEnvQueryItemType_VectorBase::StaticClass())) { UEnvQueryItemType_VectorBase* DefTypeOb = static_cast<UEnvQueryItemType_VectorBase*>(ItemType->GetDefaultObject()); return DefTypeOb->GetItemLocation(RawData.GetData() + Items[Index].DataOffset); } return FVector::ZeroVector; }
void FEnvQueryResult::GetAllAsLocations(TArray<FVector>& OutLocations) const { if (ItemType->IsChildOf(UEnvQueryItemType_VectorBase::StaticClass()) && Items.Num() > 0) { UEnvQueryItemType_VectorBase* DefTypeOb = static_cast<UEnvQueryItemType_VectorBase*>(ItemType->GetDefaultObject()); OutLocations.Reserve(OutLocations.Num() + Items.Num()); for (const FEnvQueryItem& Item : Items) { OutLocations.Add(DefTypeOb->GetItemLocation(RawData.GetData() + Item.DataOffset)); } } }
void UEnvQueryGenerator_OnCircle::GenerateItems(FEnvQueryInstance& QueryInstance) const { CircleRadius.BindData(QueryInstance.Owner.Get(), QueryInstance.QueryID); SpaceBetween.BindData(QueryInstance.Owner.Get(), QueryInstance.QueryID); ArcAngle.BindData(QueryInstance.Owner.Get(), QueryInstance.QueryID); float AngleDegree = ArcAngle.GetValue(); float RadiusValue = CircleRadius.GetValue(); float ItemSpace = SpaceBetween.GetValue(); if ((AngleDegree <= 0.f) || (AngleDegree > 360.f) || (RadiusValue <= 0.f) || (ItemSpace <= 0.f)) { return; } AngleRadians = FMath::DegreesToRadians(AngleDegree); // first generate points on a circle const float CircumferenceLength = 2.f * PI * RadiusValue; const float ArcAnglePercentage = AngleDegree / 360.f; const float ArcLength = CircumferenceLength * ArcAnglePercentage; const int32 StepsCount = FMath::CeilToInt(ArcLength / ItemSpace) + 1; const float AngleStep = AngleDegree / (StepsCount - 1); FVector StartDirection = CalcDirection(QueryInstance); StartDirection = StartDirection.RotateAngleAxis(-AngleDegree/2, FVector::UpVector) * RadiusValue; // gather context with raw data, so it can be used by derived generators FEnvQueryContextData ContextData; const bool bSuccess = QueryInstance.PrepareContext(CircleCenter, ContextData); if (bSuccess && ContextData.ValueType && ContextData.ValueType->IsChildOf(UEnvQueryItemType_VectorBase::StaticClass())) { UEnvQueryItemType_VectorBase* DefTypeOb = (UEnvQueryItemType_VectorBase*)ContextData.ValueType->GetDefaultObject(); const uint16 DefTypeValueSize = DefTypeOb->GetValueSize(); uint8* RawData = ContextData.RawData.GetData(); for (int32 ValueIndex = 0; ValueIndex < ContextData.NumValues; ValueIndex++) { const FVector ContextItemLocation = DefTypeOb->GetItemLocation(RawData); GenerateItemsForCircle(RawData, DefTypeOb, ContextItemLocation, StartDirection, StepsCount, AngleStep, QueryInstance); RawData += DefTypeValueSize; } } }