// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. #include "NiagaraEditorPrivatePCH.h" #include "NiagaraScript.h" #include "NiagaraConstants.h" #include "NiagaraEditorModule.h" #include "ComponentReregisterContext.h" #include "NiagaraComponent.h" #include "NiagaraSimulation.h" #include "NiagaraEffect.h" #include "NiagaraNodeOutput.h" #include "NiagaraNodeInput.h" #include "NiagaraNodeWriteDataSet.h" #include "NiagaraNodeReadDataSet.h" #include "EdgraphSchema_Niagara.h" ////////////////////////////////////////////////////////////////////////// // NiagaraGraph UNiagaraGraph::UNiagaraGraph(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { Schema = UEdGraphSchema_Niagara::StaticClass(); } void UNiagaraGraph::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { NotifyGraphChanged(); } class UNiagaraScriptSource* UNiagaraGraph::GetSource() const { return CastChecked(GetOuter()); } UNiagaraNodeOutput* UNiagaraGraph::FindOutputNode() const { for (UEdGraphNode* Node : Nodes) { if (UNiagaraNodeOutput* OutNode = Cast(Node)) { return OutNode; } } check(0); return NULL; } void UNiagaraGraph::FindInputNodes(TArray& OutInputNodes) const { for (UEdGraphNode* Node : Nodes) { if (UNiagaraNodeInput* InNode = Cast(Node)) { OutInputNodes.Add(InNode); } } } void UNiagaraGraph::FindReadDataSetNodes(TArray& OutReadNodes) const { for (UEdGraphNode* Node : Nodes) { if (UNiagaraNodeReadDataSet* InNode = Cast(Node)) { OutReadNodes.Add(InNode); } } } void UNiagaraGraph::FindWriteDataSetNodes(TArray& OutWriteNodes) const { for (UEdGraphNode* Node : Nodes) { if (UNiagaraNodeWriteDataSet* InNode = Cast(Node)) { OutWriteNodes.Add(InNode); } } } int32 UNiagaraGraph::GetAttributeIndex(const FNiagaraVariableInfo& Attr)const { const UNiagaraNodeOutput* OutNode = FindOutputNode(); check(OutNode); for (int32 i = 0; i < OutNode->Outputs.Num(); ++i) { if (OutNode->Outputs[i] == Attr) { return i; } } return INDEX_NONE; } void UNiagaraGraph::GetAttributes(TArray< FNiagaraVariableInfo >& OutAttributes)const { const UNiagaraNodeOutput* OutNode = FindOutputNode(); check(OutNode); for (const FNiagaraVariableInfo& Attr : OutNode->Outputs) { check(!OutAttributes.Find(Attr)); OutAttributes.Add(Attr); } } ////////////////////////////////////////////////////////////////////////// // UNiagraScriptSource UNiagaraScriptSource::UNiagaraScriptSource(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { } void UNiagaraScriptSource::PostLoad() { Super::PostLoad(); #if WITH_EDITOR UNiagaraScript* ScriptOwner = Cast(GetOuter()); if (ScriptOwner && ScriptOwner->ByteCode.Num() == 0) { ScriptOwner->ConditionalPostLoad(); //FNiagaraEditorModule& NiagaraEditorModule = FModuleManager::Get().LoadModuleChecked(TEXT("NiagaraEditor")); //NiagaraEditorModule.CompileScript(ScriptOwner); } Compile(); #endif } struct FNiagaraComponentReregisterContext : FComponentReregisterContext { FNiagaraEmitterScriptProperties* ScriptProps; UNiagaraEmitterProperties* EmitterProps; FNiagaraComponentReregisterContext(UNiagaraComponent* Comp, FNiagaraEmitterScriptProperties* InScriptProps, UNiagaraEmitterProperties* InEmitterProps) : FComponentReregisterContext(Comp) , ScriptProps(InScriptProps) , EmitterProps(InEmitterProps) { } ~FNiagaraComponentReregisterContext() { ScriptProps->Init(EmitterProps); } }; class FNiagaraScriptCompileContext { public: /** Initialization constructor. */ FNiagaraScriptCompileContext(UNiagaraScript* Script) { // wait until resources are released FlushRenderingCommands(); // Reregister all components usimg Script. for (TObjectIterator ComponentIt; ComponentIt; ++ComponentIt) { UNiagaraComponent* Comp = *ComponentIt; TSharedPtr Inst = Comp->GetEffectInstance(); if (Inst.IsValid()) { TArray>& Emitters = Inst->GetEmitters(); for (TSharedPtr Sim : Emitters) { if (Sim.IsValid()) { if (UNiagaraEmitterProperties* Props = Sim->GetProperties().Get()) { if (Props->UpdateScriptProps.Script == Script) { new(ComponentContexts)FNiagaraComponentReregisterContext(Comp, &Props->UpdateScriptProps, Props); } else if (Props->SpawnScriptProps.Script == Script) { new(ComponentContexts)FNiagaraComponentReregisterContext(Comp, &Props->SpawnScriptProps, Props); } } } } } } } private: /** The recreate contexts for the individual components. */ TIndirectArray ComponentContexts; }; void UNiagaraScriptSource::Compile() { UNiagaraScript* ScriptOwner = Cast(GetOuter()); FNiagaraScriptCompileContext ScriptCompileContext(ScriptOwner); FNiagaraEditorModule& NiagaraEditorModule = FModuleManager::Get().LoadModuleChecked(TEXT("NiagaraEditor")); NiagaraEditorModule.CompileScript(ScriptOwner); FNiagaraConstants& ExternalConsts = ScriptOwner->ConstantData.GetExternalConstants(); //Build the constant list. //This is mainly just jumping through some hoops for the custom UI. Should be removed and have the UI just read directly from the constants stored in the UScript. const UEdGraphSchema_Niagara* Schema = CastChecked(NodeGraph->GetSchema()); ExposedVectorConstants.Empty(); for (int32 ConstIdx = 0; ConstIdx < ExternalConsts.GetNumVectorConstants(); ConstIdx++) { FNiagaraVariableInfo Info; FVector4 Value; ExternalConsts.GetVectorConstant(ConstIdx, Value, Info); if (Schema->IsSystemConstant(Info)) { continue;//System constants are "external" but should not be exposed to the editor. } EditorExposedVectorConstant *Const = new EditorExposedVectorConstant(); Const->ConstName = Info.Name; Const->Value = Value; ExposedVectorConstants.Add(MakeShareable(Const)); } } void UNiagaraScriptSource::GetEmitterAttributes(TArray& VectorInputs, TArray& MatrixInputs) { for (uint32 i=0; i < NiagaraConstants::NumBuiltinConstants; i++) { VectorInputs.Add(NiagaraConstants::GConstantNames[i]); } MatrixInputs.Empty(); MatrixInputs.Add(FName(TEXT("Emitter Transform"))); }