// Fill out your copyright notice in the Description page of Project Settings. #include "NiagaraArrayBatchSubsystem.h" #include "NiagaraComponent.h" #include "NiagaraDataInterfaceArrayFunctionLibrary.h" #include "NiagaraFunctionLibrary.h" DECLARE_LOG_CATEGORY_EXTERN(LogZBS, Log, All); DEFINE_LOG_CATEGORY(LogZBS); const FName UNiagaraArrayBatchSubsystem::ParticleIDName = TEXT("User.SpawnList"); const FName UNiagaraArrayBatchSubsystem::PositionParamName = TEXT("User.Positions"); const FName UNiagaraArrayBatchSubsystem::RotationParamName = TEXT("User.Rotations"); const FName UNiagaraArrayBatchSubsystem::ColorParamName = TEXT("User.Colors"); const FName UNiagaraArrayBatchSubsystem::TextureParamName = TEXT("User.TextureIndices"); const FName UNiagaraArrayBatchSubsystem::DeadTimeName = TEXT("User.DeadTimes"); template FORCEINLINE TArray ConvertBatchDataToArray(const TArray>& InArray) { TArray Result; Result.Reserve(InArray.Num()); for (const auto& Data : InArray) { Result.Add(Data.Data); } return Result; } FNABIsland::~FNABIsland() { if (NiagaraComponent.IsValid()) { NiagaraComponent->ReleaseToPool(); } NiagaraComponent = nullptr; } void FNABIsland::Init(const FVector& Extent) { Bounds.Origin = FVector::ZeroVector; Bounds.BoxExtent = Extent; } void FNABIsland::Tick() { if (Data.bDirty) { if (!IsBeingUsed()) { FBox HandlerSystemBounds(-Bounds.BoxExtent, Bounds.BoxExtent); if (NiagaraSystem) { FFXSystemSpawnParameters SpawnParams; SpawnParams.bAutoActivate = false;//We must activate AFTER adding this component to our handle system array. SpawnParams.bAutoDestroy = false; SpawnParams.Location = Bounds.Origin; SpawnParams.PoolingMethod = EPSCPoolMethod::ManualRelease; SpawnParams.bPreCullCheck = false; SpawnParams.SystemTemplate = NiagaraSystem; SpawnParams.WorldContextObject = Subsystem.Get(); if (UNiagaraComponent* NewComp = UNiagaraFunctionLibrary::SpawnSystemAtLocationWithParams(SpawnParams)) { NiagaraComponent = NewComp; Data.NiagaraComponent = NewComp; NewComp->SetSystemFixedBounds(HandlerSystemBounds); NewComp->Activate(); } } else { UE_LOG(LogZBS, Error, TEXT("NiagaraSystem is null, unable to spawn system at location")); } } Data.ConsumeData(); } } void FNABIsland::OnAcquired(UObject* WorldContext, FVector Location) { FVector ActualMaxSize = Bounds.BoxExtent; FVector BoxSize = Bounds.BoxExtent * 2; FVector BoxN = Location / BoxSize; BoxN.X = FMath::RoundToNegativeInfinity(BoxN.X); BoxN.Y = FMath::RoundToNegativeInfinity(BoxN.Y); BoxN.Z = FMath::RoundToNegativeInfinity(BoxN.Z); Bounds.Origin = BoxN * BoxSize + Bounds.BoxExtent; Bounds.BoxExtent = ActualMaxSize; Subsystem = Cast(WorldContext); // FBox HandlerSystemBounds(-Bounds.BoxExtent, Bounds.BoxExtent); // if(NiagaraSystem) // { // FFXSystemSpawnParameters SpawnParams; // SpawnParams.bAutoActivate = false;//We must activate AFTER adding this component to our handle system array. // SpawnParams.bAutoDestroy = false; // SpawnParams.Location = Bounds.Origin; // SpawnParams.PoolingMethod = EPSCPoolMethod::ManualRelease; // SpawnParams.bPreCullCheck = false; // SpawnParams.SystemTemplate = NiagaraSystem; // SpawnParams.WorldContextObject = WorldContext; // if(UNiagaraComponent* NewComp = UNiagaraFunctionLibrary::SpawnSystemAtLocationWithParams(SpawnParams)) // { // NiagaraComponent = NewComp; // Data.NiagaraComponent = NewComp; // NewComp->SetSystemFixedBounds(HandlerSystemBounds); // NewComp->Activate(); // } // } } void FNABIsland::OnReleased() { if (NiagaraComponent.IsValid()) { NiagaraComponent->ReleaseToPool(); } NiagaraComponent = nullptr; } bool FNABIsland::IsBeingUsed() const { if (!NiagaraComponent.IsValid()) { return false; } return NiagaraComponent->IsActive(); } void FNABIslandInfo::Tick(float DeltaTime) { for (auto Iter = ActiveIslands.CreateIterator(); Iter; ++Iter) { FNABIsland& Island = IslandPool[*Iter]; if (!Island.IsBeingUsed() && !Island.IsDirty()) { Island.OnReleased(); FreeIslands.Add(*Iter); Iter.RemoveCurrent(); } else { Island.Tick(); } } } void FNiagaraArrayBatchData::ConsumeData() { QUICK_SCOPE_CYCLE_COUNTER(NiagaraArrayBatchData_ConsumeData); bDirty = false; if (!NiagaraComponent.IsValid()) { return; } for (const auto& Data : VectorData) { UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayVector(NiagaraComponent.Get(), Data.Key, ConvertBatchDataToArray(Data.Value)); } for (const auto& Data : FloatData) { UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayFloat(NiagaraComponent.Get(), Data.Key, ConvertBatchDataToArray(Data.Value)); } for (const auto& Data : IntData) { UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(NiagaraComponent.Get(), Data.Key, ConvertBatchDataToArray(Data.Value)); } for (const auto& Data : ColorData) { UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayColor(NiagaraComponent.Get(), Data.Key, ConvertBatchDataToArray(Data.Value)); } for (const auto& Data : QuatData) { UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayQuat(NiagaraComponent.Get(), Data.Key, ConvertBatchDataToArray(Data.Value)); } for (const auto& Data : BoolData) { UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayBool(NiagaraComponent.Get(), Data.Key, ConvertBatchDataToArray(Data.Value)); } for (const auto& Data : Vector2DData) { UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayVector2D(NiagaraComponent.Get(), Data.Key, ConvertBatchDataToArray(Data.Value)); } } void UNiagaraArrayBatchSubsystem::Tick(float DeltaTime) { QUICK_SCOPE_CYCLE_COUNTER(NiagaraArrayBatchSubsystem_Tick); Super::Tick(DeltaTime); for (auto Iter = NiagaraIslandInfoMap.CreateIterator(); Iter; ++Iter) { if (!Iter->Key.IsValid()) { Iter.RemoveCurrent(); continue; } Iter->Value.Tick(DeltaTime); } } FNABIsland* UNiagaraArrayBatchSubsystem::FindOrCreateIsland(UNiagaraSystem* NiagaraSystem, const FVector& Location, int32& IslandIndex) { //Find the first island that could contain this point. //For now we do a linear search of active islands. //Assuming that overall active island count will be low. //If this is not the case then we'll want to add an acceleration structure to speed up this search. if (!bLoadedIslandExtents) { bLoadedIslandExtents = true; NiagaraIslandExtentsMap = GetNiagaraIslandExtents(); } auto& NABIslandInfo = NiagaraIslandInfoMap.FindOrAdd(NiagaraSystem); if (FVector* Ret = NiagaraIslandExtentsMap.Find(NiagaraSystem->GetPackage()->GetPathName())) { NABIslandInfo.Extent = *Ret; } FNABIsland* IslandToUse = nullptr; for (int32 i : NABIslandInfo.ActiveIslands) { FNABIsland& Island = NABIslandInfo.IslandPool[i]; if (Island.Contains(Location)) { IslandToUse = &Island; IslandIndex = i; } } if (IslandToUse) { return IslandToUse; } //Failing that, get a init a new island from the pool. int32 NewIslandIndex = ActivateNewIsland(NiagaraSystem, NABIslandInfo, Location); if (ensure(NewIslandIndex != INDEX_NONE)) { IslandToUse = &NABIslandInfo.IslandPool[NewIslandIndex]; IslandIndex = NewIslandIndex; } if (IslandToUse) { IslandToUse->OnAcquired(this, Location); } return IslandToUse; } int32 UNiagaraArrayBatchSubsystem::ActivateNewIsland(UNiagaraSystem* NiagaraSystem, FNABIslandInfo& FNABIslandInfo, FVector Location) { int32 NewIndex = INDEX_NONE; FNABIsland* NewIsland = nullptr; if (FNABIslandInfo.FreeIslands.Num() > 0) { NewIndex = FNABIslandInfo.FreeIslands.Pop(false); NewIsland = &FNABIslandInfo.IslandPool[NewIndex]; } if (NewIsland == nullptr) { NewIndex = FNABIslandInfo.IslandPool.Num(); NewIsland = &FNABIslandInfo.IslandPool.AddDefaulted_GetRef(); } if (NewIndex != INDEX_NONE) { check(NewIsland); FNABIslandInfo.ActiveIslands.Add(NewIndex); NewIsland->NiagaraSystem = NiagaraSystem; NewIsland->Init(FNABIslandInfo.Extent); } return NewIndex; } int64 FNABParticleData::GetUUID() { return static_cast(IslandIndex) << 32 | ParticleID; } TArray& FNABParticleData::GetPropertys() { return Propertys; } FNABParticleData& FNABParticleData::WriteVector(FName Name, const FVector& Value) { if (DataPtr) { Propertys.Add(FNiagaraBatchProperty{ ENiagaraBatchDataType::Vector, Name }); DataPtr->VectorData.FindOrAdd(Name).Add({ ParticleID, Value }); DataPtr->bDirty = true; } return *this; } FNABParticleData& FNABParticleData::WriteQuat(FName Name, const FQuat& Value) { if (DataPtr) { Propertys.Add(FNiagaraBatchProperty{ ENiagaraBatchDataType::Quat, Name }); DataPtr->QuatData.FindOrAdd(Name).Add({ ParticleID, Value }); DataPtr->bDirty = true; } return *this; } FNABParticleData& FNABParticleData::WriteColor(FName Name, const FLinearColor& Value) { if (DataPtr) { Propertys.Add(FNiagaraBatchProperty{ ENiagaraBatchDataType::Color, Name }); DataPtr->ColorData.FindOrAdd(Name).Add({ ParticleID, Value }); DataPtr->bDirty = true; } return *this; } FNABParticleData& FNABParticleData::WriteInt(FName Name, int32 Value) { if (DataPtr) { Propertys.Add(FNiagaraBatchProperty{ ENiagaraBatchDataType::Int32, Name }); DataPtr->IntData.FindOrAdd(Name).Add({ ParticleID, Value }); DataPtr->bDirty = true; } return *this; } FNABParticleData& FNABParticleData::WriteFloat(FName Name, float Value) { if (DataPtr) { Propertys.Add(FNiagaraBatchProperty{ ENiagaraBatchDataType::Float, Name }); DataPtr->FloatData.FindOrAdd(Name).Add({ ParticleID, Value }); DataPtr->bDirty = true; } return *this; } FNABParticleData& FNABParticleData::WriteBool(FName Name, bool Value) { if (DataPtr) { Propertys.Add(FNiagaraBatchProperty{ ENiagaraBatchDataType::Bool, Name }); DataPtr->BoolData.FindOrAdd(Name).Add({ ParticleID, Value }); DataPtr->bDirty = true; } return *this; } FNABParticleData UNiagaraArrayBatchSubsystem::WriteNABParticle(UNiagaraSystem* NiagaraAsset, const FVector& Location) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; return FNABParticleData{ DataUid , IslandIndex , &Data }.WriteInt(ParticleIDName, DataUid); } template void RemoveProperty(TMap>>& Data, FName Name, int64 DataUid) { Data.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::RemoveNABParticle(UNiagaraSystem* NiagaraAsset, int64 DataUid, const TArray& Propertys) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; for (auto& Property : Propertys) { ENiagaraBatchDataType Type = Property.Type; FName Name = Property.Name; switch (Type) { case ENiagaraBatchDataType::Vector: RemoveProperty(Data.VectorData, Name, DataUid); break; case ENiagaraBatchDataType::Float: RemoveProperty(Data.FloatData, Name, DataUid); break; case ENiagaraBatchDataType::Int32: RemoveProperty(Data.IntData, Name, DataUid); break; case ENiagaraBatchDataType::Color: RemoveProperty(Data.ColorData, Name, DataUid); break; case ENiagaraBatchDataType::Quat: RemoveProperty(Data.QuatData, Name, DataUid); break; case ENiagaraBatchDataType::Bool: RemoveProperty(Data.BoolData, Name, DataUid); break; case ENiagaraBatchDataType::Vector2D: RemoveProperty(Data.Vector2DData, Name, DataUid); break; default: ensureMsgf(false, TEXT("%s Failed to remove property %d %s"), *NiagaraAsset->GetName(), Type, *Name.ToString()); } } } void UNiagaraArrayBatchSubsystem::WriteNABVector(FNABParticleData& Data, FName Name, const FVector& Value) { Data.WriteVector(Name, Value); } void UNiagaraArrayBatchSubsystem::WriteNABQuat(FNABParticleData& Data, FName Name, const FQuat& Value) { Data.WriteQuat(Name, Value); } void UNiagaraArrayBatchSubsystem::WriteNABColor(FNABParticleData& Data, FName Name, const FLinearColor& Value) { Data.WriteColor(Name, Value); } void UNiagaraArrayBatchSubsystem::WriteNABInt(FNABParticleData& Data, FName Name, int32 Value) { Data.WriteInt(Name, Value); } void UNiagaraArrayBatchSubsystem::WriteNABFloat(FNABParticleData& Data, FName Name, float Value) { Data.WriteFloat(Name, Value); } void UNiagaraArrayBatchSubsystem::WriteNABBool(FNABParticleData& Data, FName Name, bool Value) { Data.WriteBool(Name, Value); } int64 UNiagaraArrayBatchSubsystem::WriteVector(UNiagaraSystem* NiagaraAsset, const FVector& Location, FName Name, const FVector& Value) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; Data.VectorData.FindOrAdd(Name).Add({ DataUid, Value }); Data.bDirty = true; return static_cast(IslandIndex) << 32 | DataUid; } int64 UNiagaraArrayBatchSubsystem::WriteFloat(UNiagaraSystem* NiagaraAsset, const FVector& Location, FName Name, float Value) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; Data.FloatData.FindOrAdd(Name).Add({ DataUid, Value }); Data.bDirty = true; return static_cast(IslandIndex) << 32 | DataUid; } int64 UNiagaraArrayBatchSubsystem::WriteInt(UNiagaraSystem* NiagaraAsset, const FVector& Location, FName Name, int32 Value) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; Data.IntData.FindOrAdd(Name).Add({ DataUid, Value }); Data.bDirty = true; return static_cast(IslandIndex) << 32 | DataUid; } int64 UNiagaraArrayBatchSubsystem::WriteColor(UNiagaraSystem* NiagaraAsset, const FVector& Location, FName Name, const FLinearColor& Value) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; Data.ColorData.FindOrAdd(Name).Add({ DataUid, Value }); Data.bDirty = true; return static_cast(IslandIndex) << 32 | DataUid; } int64 UNiagaraArrayBatchSubsystem::WriteQuat(UNiagaraSystem* NiagaraAsset, const FVector& Location, FName Name, const FQuat& Value) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; Data.QuatData.FindOrAdd(Name).Add({ DataUid, Value }); Data.bDirty = true; return static_cast(IslandIndex) << 32 | DataUid; } int64 UNiagaraArrayBatchSubsystem::WriteBool(UNiagaraSystem* NiagaraAsset, const FVector& Location, FName Name, bool Value) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; Data.BoolData.FindOrAdd(Name).Add({ DataUid, Value }); Data.bDirty = true; return static_cast(IslandIndex) << 32 | DataUid; } int64 UNiagaraArrayBatchSubsystem::WriteVector2D(UNiagaraSystem* NiagaraAsset, const FVector& Location, FName Name, const FVector2D& Value) { if (!NiagaraAsset) { return 0; } int32 IslandIndex; auto* Island = FindOrCreateIsland(NiagaraAsset, Location, IslandIndex); if (!ensureMsgf(Island, TEXT("Failed to find or create island for %s"), *NiagaraAsset->GetName())) { return 0; } auto DataUid = ++Island->DataUid; FNiagaraArrayBatchData& Data = Island->Data; Data.Vector2DData.FindOrAdd(Name).Add({ DataUid, Value }); Data.bDirty = true; return static_cast(IslandIndex) << 32 | DataUid; } void UNiagaraArrayBatchSubsystem::OverrideVector(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid, const FVector& Value) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.VectorData.FindOrAdd(Name).FindByPredicate([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); })->Data = Value; } void UNiagaraArrayBatchSubsystem::OverrideFloat(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid, float Value) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.FloatData.FindOrAdd(Name).FindByPredicate([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid);; })->Data = Value; } void UNiagaraArrayBatchSubsystem::OverrideInt(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid, int32 Value) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.IntData.FindOrAdd(Name).FindByPredicate([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid);; })->Data = Value; } void UNiagaraArrayBatchSubsystem::OverrideColor(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid, const FLinearColor& Value) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.ColorData.FindOrAdd(Name).FindByPredicate([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid);; })->Data = Value; } void UNiagaraArrayBatchSubsystem::OverrideQuat(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid, const FQuat& Value) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.QuatData.FindOrAdd(Name).FindByPredicate([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid);; })->Data = Value; } void UNiagaraArrayBatchSubsystem::OverrideBool(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid, bool Value) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.BoolData.FindOrAdd(Name).FindByPredicate([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid);; })->Data = Value; } void UNiagaraArrayBatchSubsystem::RemoveVector(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.VectorData.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::RemoveFloat(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.FloatData.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::RemoveInt(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.IntData.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::RemoveColor(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.ColorData.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::RemoveQuat(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid) { if (DataUid == 0) { return; } if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.QuatData.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::RemoveBool(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid) { if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.BoolData.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::RemoveVector2D(UNiagaraSystem* NiagaraAsset, FName Name, int64 DataUid) { if (!NiagaraAsset) { return; } int32 IslandIndex = DataUid >> 32; auto* IslandInfo = NiagaraIslandInfoMap.Find(NiagaraAsset); if (!ensureMsgf(IslandInfo, TEXT("Failed to find island for %s"), *NiagaraAsset->GetName())) { return; } if (!IslandInfo->IslandPool.IsValidIndex(IslandIndex)) { return; } auto& Island = IslandInfo->IslandPool[IslandIndex]; FNiagaraArrayBatchData& Data = Island.Data; Data.bDirty = true; Data.Vector2DData.FindOrAdd(Name).RemoveAll([DataUid](const FNiagaraBatchData& InData) { return InData.DataUid == static_cast(DataUid); }); } void UNiagaraArrayBatchSubsystem::SetNiagaraHidden(const FString& NiagaraFullName, bool bHide, FName HideTag) { for (auto& Pair : NiagaraIslandInfoMap) { if (!Pair.Key.IsValid()) { continue; } if (Pair.Key->GetPathName() == NiagaraFullName) { for (auto& Island : Pair.Value.IslandPool) { if (!Island.NiagaraComponent.IsValid()) { continue; } //TArray HiddenComponents; //URuntimeCommonFunctionLibrary::SetSceneComponentHiddenInGame(Island.NiagaraComponent.Get(), bHide, false, HideTag, HiddenComponents); } break; } } }