// Copyright Epic Games, Inc. All Rights Reserved. #include "UpgradeNiagaraScriptResults.h" #include "NiagaraClipboard.h" #include "NiagaraEmitterHandle.h" #include "NiagaraNodeFunctionCall.h" #include "Logging/StructuredLog.h" #include "ViewModels/NiagaraEmitterHandleViewModel.h" #include "ViewModels/NiagaraEmitterViewModel.h" #include "ViewModels/Stack/NiagaraStackModuleItem.h" #include "ViewModels/Stack/NiagaraStackViewModel.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(UpgradeNiagaraScriptResults) namespace NiagaraScriptResults { template TArray GetStackEntries(UNiagaraStackViewModel* StackViewModel, bool bRefresh = false) { TArray Results; TArray EntriesToCheck; if (UNiagaraStackEntry* RootEntry = StackViewModel->GetRootEntry()) { if (bRefresh) { RootEntry->RefreshChildren(); } RootEntry->GetUnfilteredChildren(EntriesToCheck); } while (EntriesToCheck.Num() > 0) { UNiagaraStackEntry* Entry = EntriesToCheck.Pop(); if (T* ItemToCheck = Cast(Entry)) { Results.Add(ItemToCheck); } Entry->GetUnfilteredChildren(EntriesToCheck); } return Results; } template T GetValue(const UNiagaraClipboardFunctionInput* Input) { T Value; if (Input == nullptr || Input->InputType.GetSize() != sizeof(T) || Input->Local.Num() != sizeof(T)) { FMemory::Memzero(Value); } else { FMemory::Memcpy(&Value, Input->Local.GetData(), sizeof(T)); } return Value; } template void SetValue(UNiagaraPythonScriptModuleInput* ModuleInput, T Data) { TArray LocalData; LocalData.SetNumZeroed(sizeof(T)); FMemory::Memcpy(LocalData.GetData(), &Data, sizeof(T)); const UNiagaraClipboardFunctionInput* Input = ModuleInput->Input; ModuleInput->Input = UNiagaraClipboardFunctionInput::CreateLocalValue(ModuleInput, Input->InputName, Input->InputType, Input->bEditConditionValue, LocalData); } } bool UNiagaraPythonScriptModuleInput::IsSet() const { return Input && Input->InputType.IsValid(); } bool UNiagaraPythonScriptModuleInput::IsLocalValue() const { return IsSet() && Input->ValueMode == ENiagaraClipboardFunctionInputValueMode::Local; } bool UNiagaraPythonScriptModuleInput::IsLinkedValue() const { return IsSet() && Input->ValueMode == ENiagaraClipboardFunctionInputValueMode::Linked; } float UNiagaraPythonScriptModuleInput::AsFloat() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetFloatDef()) { FNiagaraVariable LocalInput; return NiagaraScriptResults::GetValue(Input); } return 0; } int32 UNiagaraPythonScriptModuleInput::AsInt() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetIntDef()) { return NiagaraScriptResults::GetValue(Input); } if (IsSet() && Input->InputType.IsEnum()) { return NiagaraScriptResults::GetValue(Input); } return 0; } bool UNiagaraPythonScriptModuleInput::AsBool() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetBoolDef()) { if (Input->Local.Num() != sizeof(FNiagaraBool)) { return false; } const FNiagaraBool* BoolStruct = reinterpret_cast(Input->Local.GetData()); return BoolStruct->GetValue(); } return false; } FVector2D UNiagaraPythonScriptModuleInput::AsVec2() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetVec2Def()) { return NiagaraScriptResults::GetValue(Input); } return FVector2D(); } FVector UNiagaraPythonScriptModuleInput::AsVec3() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetVec3Def()) { return FVector(NiagaraScriptResults::GetValue(Input)); } return FVector(); } FVector4 UNiagaraPythonScriptModuleInput::AsVec4() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetVec4Def()) { return FVector4(NiagaraScriptResults::GetValue(Input)); } return FVector4(); } FLinearColor UNiagaraPythonScriptModuleInput::AsColor() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetColorDef()) { return NiagaraScriptResults::GetValue(Input); } return FLinearColor(); } FQuat UNiagaraPythonScriptModuleInput::AsQuat() const { if (IsSet() && Input->InputType == FNiagaraTypeDefinition::GetQuatDef()) { return NiagaraScriptResults::GetValue(Input); } return FQuat(); } FString UNiagaraPythonScriptModuleInput::AsEnum() const { if (IsSet() && Input->InputType.IsEnum()) { int32 Value = NiagaraScriptResults::GetValue(Input); return Input->InputType.GetEnum()->GetNameStringByValue(Value); } return FString(); } FString UNiagaraPythonScriptModuleInput::AsLinkedValue() const { if (IsLinkedValue()) { return Input->Linked.GetName().ToString(); } return FString(); } UUpgradeNiagaraScriptResults::UUpgradeNiagaraScriptResults() { DummyInput = NewObject(); } void UUpgradeNiagaraScriptResults::Init() { // if some of the old inputs are missing in the new inputs we still bring them over, otherwise they can't be set from the script for (UNiagaraPythonScriptModuleInput* OldInput : OldInputs) { UNiagaraPythonScriptModuleInput* NewInput = GetNewInput(OldInput->Input->InputName); if (NewInput == nullptr) { UNiagaraPythonScriptModuleInput* ScriptInput = NewObject(); ScriptInput->Input = OldInput->Input; NewInputs.Add(ScriptInput); } } } UNiagaraPythonScriptModuleInput* UUpgradeNiagaraScriptResults::GetOldInput(const FString& InputName) { for (UNiagaraPythonScriptModuleInput* ModuleInput : OldInputs) { if (ModuleInput->Input->InputName == FName(InputName)) { return ModuleInput; } } return DummyInput; } void UUpgradeNiagaraScriptResults::SetFloatInput(const FString& InputName, float Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetFloatDef()) { NiagaraScriptResults::SetValue(ModuleInput, Value); } } void UUpgradeNiagaraScriptResults::SetIntInput(const FString& InputName, int32 Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetIntDef()) { NiagaraScriptResults::SetValue(ModuleInput, Value); } } void UUpgradeNiagaraScriptResults::SetBoolInput(const FString& InputName, bool Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetBoolDef()) { ModuleInput->Input = UNiagaraClipboardEditorScriptingUtilities::CreateBoolLocalValueInput(ModuleInput, FName(InputName), false, false, Value); } } void UUpgradeNiagaraScriptResults::SetVec2Input(const FString& InputName, FVector2D Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetVec2Def()) { NiagaraScriptResults::SetValue(ModuleInput, FVector2f(Value)); } } void UUpgradeNiagaraScriptResults::SetVec3Input(const FString& InputName, FVector Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetVec3Def()) { NiagaraScriptResults::SetValue(ModuleInput, FVector3f(Value)); } } void UUpgradeNiagaraScriptResults::SetVec4Input(const FString& InputName, FVector4 Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetVec4Def()) { NiagaraScriptResults::SetValue(ModuleInput, FVector4f(Value)); } } void UUpgradeNiagaraScriptResults::SetColorInput(const FString& InputName, FLinearColor Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetColorDef()) { NiagaraScriptResults::SetValue(ModuleInput, Value); } } void UUpgradeNiagaraScriptResults::SetQuatInput(const FString& InputName, FQuat Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType == FNiagaraTypeDefinition::GetQuatDef()) { NiagaraScriptResults::SetValue(ModuleInput, FQuat4f(Value)); } } void UUpgradeNiagaraScriptResults::SetEnumInput(const FString& InputName, FString Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType.IsEnum()) { int32 EnumValue = ModuleInput->Input->InputType.GetEnum()->GetValueByNameString(Value, EGetByNameFlags::ErrorIfNotFound | EGetByNameFlags::CheckAuthoredName); NiagaraScriptResults::SetValue(ModuleInput, EnumValue); } } void UUpgradeNiagaraScriptResults::SetEnumInputFromInt(const FString& InputName, int32 Value) { UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName)); if (ModuleInput && ModuleInput->Input->InputType.IsEnum()) { if (!ModuleInput->Input->InputType.GetEnum()->IsValidEnumValue(Value)) { UE_LOGFMT(LogNiagaraEditor, Error, "Value {Value} is not a valid enum value for input {InputName}", Value, InputName); } NiagaraScriptResults::SetValue(ModuleInput, Value); } } void UUpgradeNiagaraScriptResults::SetLinkedInput(const FString& InputName, FString Value) { if (UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName))) { const UNiagaraClipboardFunctionInput* CurrentInput = ModuleInput->Input; FNiagaraVariableBase LinkedParameter = FNiagaraVariableBase(CurrentInput->InputType, *Value); ModuleInput->Input = UNiagaraClipboardFunctionInput::CreateLinkedValue(ModuleInput, CurrentInput->InputName, CurrentInput->InputType, CurrentInput->bEditConditionValue, LinkedParameter); } } void UUpgradeNiagaraScriptResults::SetNewInput(const FString& InputName, UNiagaraPythonScriptModuleInput* Value) { for (int i = 0; i < NewInputs.Num(); i++) { UNiagaraPythonScriptModuleInput* ModuleInput = NewInputs[i]; UNiagaraClipboardFunctionInput* FunctionInput = const_cast(ModuleInput->Input.Get()); if (Value && FunctionInput && FunctionInput->InputName == InputName ) { if (Value->IsSet() && FunctionInput->InputType == Value->Input->InputType) { FunctionInput->Data = Value->Input->Data; FunctionInput->Dynamic = Value->Input->Dynamic; FunctionInput->Expression = Value->Input->Expression; FunctionInput->Linked = Value->Input->Linked; FunctionInput->Local = Value->Input->Local; FunctionInput->ValueMode = Value->Input->ValueMode; } else { ResetToDefault(InputName); } return; } } } void UUpgradeNiagaraScriptResults::ResetToDefault(const FString& InputName) { if (UNiagaraPythonScriptModuleInput* ModuleInput = GetNewInput(FName(InputName))) { const UNiagaraClipboardFunctionInput* CurrentInput = ModuleInput->Input; ModuleInput->Input = UNiagaraClipboardFunctionInput::CreateDefaultInputValue(ModuleInput, CurrentInput->InputName, CurrentInput->InputType); } } UNiagaraPythonScriptModuleInput* UUpgradeNiagaraScriptResults::GetNewInput(const FName& InputName) const { for (UNiagaraPythonScriptModuleInput* ModuleInput : NewInputs) { if (ModuleInput->Input && ModuleInput->Input->InputName == InputName) { return ModuleInput; } } return nullptr; } void UNiagaraPythonModule::Init(UNiagaraStackModuleItem* InModuleItem) { ModuleItem = InModuleItem; } UNiagaraStackModuleItem* UNiagaraPythonModule::GetObject() const { return ModuleItem; } void UNiagaraPythonEmitter::Init(TSharedRef InEmitterViewModel) { EmitterViewModel = InEmitterViewModel; } UNiagaraEmitter* UNiagaraPythonEmitter::GetObject() { return EmitterViewModel->GetEmitterViewModel()->GetEmitter().Emitter; } FVersionedNiagaraEmitterData UNiagaraPythonEmitter::GetProperties() const { if (EmitterViewModel->GetEmitterViewModel()->GetEmitter().GetEmitterData()) { return *EmitterViewModel->GetEmitterViewModel()->GetEmitter().GetEmitterData(); } return FVersionedNiagaraEmitterData(); } void UNiagaraPythonEmitter::SetProperties(FVersionedNiagaraEmitterData Data) { if (EmitterViewModel->GetEmitterViewModel()->GetEmitter().GetEmitterData()) { FVersionedNiagaraEmitterData* EmitterData = EmitterViewModel->GetEmitterViewModel()->GetEmitter().GetEmitterData(); for (TFieldIterator PropertyIterator(FVersionedNiagaraEmitterData::StaticStruct()); PropertyIterator; ++PropertyIterator) { if (PropertyIterator->HasAllPropertyFlags(CPF_Edit)) { void* Dest = PropertyIterator->ContainerPtrToValuePtr(EmitterData); void* Src = PropertyIterator->ContainerPtrToValuePtr(&Data); PropertyIterator->CopyCompleteValue(Dest, Src); } } } } TArray UNiagaraPythonEmitter::GetModules() const { TArray Result; if (UNiagaraStackViewModel* StackViewModel = EmitterViewModel->GetEmitterStackViewModel()) { TArray StackModuleItems = NiagaraScriptResults::GetStackEntries(StackViewModel); for (UNiagaraStackModuleItem* ModuleItem : StackModuleItems) { UNiagaraPythonModule* Module = NewObject(); Module->Init(ModuleItem); Result.Add(Module); } } return Result; } bool UNiagaraPythonEmitter::HasModule(const FString& ModuleName) const { return GetModule(ModuleName)->GetObject() != nullptr; } UNiagaraPythonModule* UNiagaraPythonEmitter::GetModule(const FString& ModuleName) const { UNiagaraPythonModule* Module = NewObject(); if (UNiagaraStackViewModel* StackViewModel = EmitterViewModel->GetEmitterStackViewModel()) { TArray StackModuleItems = NiagaraScriptResults::GetStackEntries(StackViewModel); for (UNiagaraStackModuleItem* ModuleItem : StackModuleItems) { if (ModuleItem->GetModuleNode().GetFunctionName() == ModuleName) { Module->Init(ModuleItem); break; } } } return Module; } void UUpgradeNiagaraEmitterContext::Init(UNiagaraPythonEmitter* InOldEmitter, UNiagaraPythonEmitter* InNewEmitter) { OldEmitter = InOldEmitter; NewEmitter = InNewEmitter; UpgradeVersionData.Empty(); if (!IsValid()) { return; } FVersionedNiagaraEmitterData* SourceData = OldEmitter->EmitterViewModel->GetEmitterHandle()->GetInstance().GetEmitterData(); FVersionedNiagaraEmitterData* TargetData = NewEmitter->EmitterViewModel->GetEmitterHandle()->GetInstance().GetEmitterData(); FVersionedNiagaraEmitter SourceParent = SourceData->GetParent(); FVersionedNiagaraEmitter TargetParent = TargetData->GetParent(); FNiagaraAssetVersion SourceVersion = SourceParent.GetEmitterData()->Version; FNiagaraAssetVersion TargetVersion = TargetParent.GetEmitterData()->Version; // gather script required to execute for (const FNiagaraAssetVersion& Version : SourceParent.Emitter->GetAllAvailableVersions()) { if (SourceVersion <= Version && Version <= TargetVersion) { FVersionedNiagaraEmitterData* ParentData = SourceParent.Emitter->GetEmitterData(Version.VersionGuid); UpgradeVersionData.Add(ParentData); } } } bool UUpgradeNiagaraEmitterContext::IsValid() const { return OldEmitter && OldEmitter->IsValid() && NewEmitter && NewEmitter->IsValid(); } const TArray& UUpgradeNiagaraEmitterContext::GetUpgradeData() const { return UpgradeVersionData; }