Esempio n. 1
0
void UNiagaraNodeOutput::Compile(class INiagaraCompiler* Compiler, TArray<FNiagaraNodeResult>& OutputExpressions)
{
	TArray<TNiagaraExprPtr> InputExpressions;

	for (int32 i = 0; i < Outputs.Num(); ++i)
	{
		const FNiagaraVariableInfo& Out = Outputs[i];
		UEdGraphPin* Pin = Pins[i];
		check(Pin->Direction == EGPD_Input);

		TNiagaraExprPtr Result = Compiler->CompilePin(Pin);
		if (!Result.IsValid())
		{
			//The pin was not connected so pass through the initial value of the attribute.
			Result = Compiler->GetAttribute(Out);
		}

		InputExpressions.Add(Result);
	}

	check(Outputs.Num() == InputExpressions.Num());
	for (int32 i = 0; i < Outputs.Num(); ++i)
	{
		OutputExpressions.Add(FNiagaraNodeResult(Compiler->Output(Outputs[i], InputExpressions[i]), Pins[i]));
	}
}
void UNiagaraNodeWriteDataSet::Compile(class INiagaraCompiler* Compiler, TArray<FNiagaraNodeResult>& Outputs)
{
	bool bError = false;

	if (DataSet.Type == ENiagaraDataSetType::Event)
	{
		//Compile the Emit pin.
		TNiagaraExprPtr EmitExpression = Compiler->CompilePin(Pins[0]);

		if (EmitExpression.IsValid())
		{
			//Test the Valid pin result against 0. Maybe just require a direct connection of 0 or 0xFFFFFFFF?
			FNiagaraVariableInfo Zero(TEXT("0.0, 0.0, 0.0, 0.0"), ENiagaraDataType::Vector);
			TNiagaraExprPtr ZeroContantExpression = Compiler->GetInternalConstant(Zero, FVector4(0.0f, 0.0f, 0.0f, 0.0f));
			TArray<TNiagaraExprPtr> ConditonInputs;
			ConditonInputs.Add(EmitExpression);
			ConditonInputs.Add(ZeroContantExpression);
			check(ZeroContantExpression.IsValid());
			TArray<TNiagaraExprPtr> ConditionOpOutputs;
			INiagaraCompiler::GreaterThan(Compiler, ConditonInputs, ConditionOpOutputs);
			TNiagaraExprPtr ValidExpr = ConditionOpOutputs[0];

			TArray<TNiagaraExprPtr> InputExpressions;
			for (int32 i = 0; i < Variables.Num(); ++i)
			{
				const FNiagaraVariableInfo& Var = Variables[i];
				UEdGraphPin* Pin = Pins[i + 1];//Pin[0] is emit
				check(Pin->Direction == EGPD_Input);

				TNiagaraExprPtr Result = Compiler->CompilePin(Pin);
				if (!Result.IsValid())
				{
					bError = true;
					Compiler->Error(FText::Format(LOCTEXT("DataSetWriteErrorFormat", "Error writing variable {0} to dataset {1}"), FText::FromName(DataSet.Name), Pin->PinFriendlyName), this, Pin);
				}

				InputExpressions.Add(Result);
			}

			//Gets the index to write to. 
			TNiagaraExprPtr IndexExpression = Compiler->AcquireSharedDataIndex(DataSet, true, ValidExpr);

			if (!bError)
			{
				check(Variables.Num() == InputExpressions.Num());
				for (int32 i = 0; i < Variables.Num(); ++i)
				{
					Outputs.Add(FNiagaraNodeResult(Compiler->SharedDataWrite(DataSet, Variables[i], IndexExpression, InputExpressions[i]), Pins[i + 1]));//Pin[0] is Emit
				}
			}
		}
	}
	else
	{
		check(false);//IMPLEMENT OTHER DATA SETS.
	}
}
void UNiagaraNodeReadDataSet::Compile(class INiagaraCompiler* Compiler, TArray<FNiagaraNodeResult>& Outputs)
{
	if(DataSet.Type == ENiagaraDataSetType::Event)
	{
		TNiagaraExprPtr IndexExpr = Compiler->ConsumeSharedDataIndex(DataSet, true);//Where do we decide wrapping?
		check(Variables.Num() == Pins.Num() - 1);//We should have a pin for each variable + 1 for the Valid pin.
		Outputs.Add(FNiagaraNodeResult(Compiler->SharedDataIndexIsValid(DataSet, IndexExpr), Pins[0]));
		for (int32 i = 0; i < Variables.Num(); ++i)
		{
			check(Variables[i].Type == ENiagaraDataType::Vector);//Only support vectors currently.
			Outputs.Add(FNiagaraNodeResult(Compiler->SharedDataRead(DataSet, Variables[i], IndexExpr), Pins[i+1]));
		}
	}
	else
	{
		Compiler->Error(LOCTEXT("UnImplDataSetTypeError", "This data set type hasn't been implemented."), this, nullptr);
	}
	
}
void UNiagaraNodeOp::Compile(class INiagaraCompiler* Compiler, TArray<FNiagaraNodeResult>& Outputs)
{
	const FNiagaraOpInfo* OpInfo = FNiagaraOpInfo::GetOpInfo(OpName);
	check(OpInfo);
	int32 NumInputs = OpInfo->Inputs.Num();
	int32 NumOutputs = OpInfo->Outputs.Num();

	TArray<TNiagaraExprPtr> Inputs;
	bool bError = false;
	for (int32 i = 0; i < NumInputs; ++i)
	{
		UEdGraphPin *Pin = Pins[i];
		check(Pin->Direction == EGPD_Input);
		TNiagaraExprPtr InputExpr = Compiler->CompilePin(Pin);
		if (!InputExpr.IsValid())
		{
			bError = true;
			FFormatNamedArguments Args;
			Args.Add(TEXT("OpName"), GetNodeTitle(ENodeTitleType::FullTitle));
			FText Format = LOCTEXT("InputErrorFormat", "Error compiling input on {OpName} node.");
			Compiler->Error(FText::Format(Format, Args), this, Pin);
		}
		Inputs.Add(InputExpr);
	}
	
	TArray<TNiagaraExprPtr> OutputExpressions;
	if ( !bError && OpInfo->OpDelegate.Execute(Compiler, Inputs, OutputExpressions))
	{
		check(OutputExpressions.Num() == OpInfo->Outputs.Num());

		for (int32 i = 0; i < NumOutputs; ++i)
		{
			UEdGraphPin *Pin = Pins[NumInputs + i];
			check(Pin->Direction == EGPD_Output);
			Outputs.Add(FNiagaraNodeResult(OutputExpressions[i], Pin));
		}
	}
	else
	{
		FFormatNamedArguments Args;
		Args.Add(TEXT("OpName"), GetNodeTitle(ENodeTitleType::FullTitle));
		FText Format = LOCTEXT("NodeErrorFormat", "Error compiling {OpName} node.");
		Compiler->Error(FText::Format(Format, Args), this, nullptr);
	}
}
void UNiagaraNodeInput::Compile(class INiagaraCompiler* Compiler, TArray<FNiagaraNodeResult>& Outputs)
{
	//Input nodes in scripts being used as functions by other scripts will actually never get this far.
	//The compiler will find them and replace them with direct links between the pins going in and the nodes connected to the corresponding input.

	const UEdGraphSchema_Niagara* Schema = CastChecked<UEdGraphSchema_Niagara>(GetSchema());
	if (IsConstant())
	{
		if (IsExposedConstant() || Schema->IsSystemConstant(Input))
		{
			//treat this input as an external constant.
			switch (Input.Type)
			{
			case ENiagaraDataType::Scalar:	Outputs.Add(FNiagaraNodeResult(Compiler->GetExternalConstant(Input, FloatDefault), Pins[0]));	break;
			case ENiagaraDataType::Vector:	Outputs.Add(FNiagaraNodeResult(Compiler->GetExternalConstant(Input, VectorDefault), Pins[0]));	break;
			case ENiagaraDataType::Matrix:	Outputs.Add(FNiagaraNodeResult(Compiler->GetExternalConstant(Input, MatrixDefault), Pins[0]));	break;
			case ENiagaraDataType::Curve:	Outputs.Add(FNiagaraNodeResult(Compiler->GetExternalConstant(Input, DataObjectDefault), Pins[0]));	break;
			}
		}
		else
		{
			//treat this input as an internal constant.
			switch (Input.Type)
			{
			case ENiagaraDataType::Scalar:	Outputs.Add(FNiagaraNodeResult(Compiler->GetInternalConstant(Input, FloatDefault), Pins[0]));	break;
			case ENiagaraDataType::Vector:	Outputs.Add(FNiagaraNodeResult(Compiler->GetInternalConstant(Input, VectorDefault), Pins[0]));	break;
			case ENiagaraDataType::Matrix:	Outputs.Add(FNiagaraNodeResult(Compiler->GetInternalConstant(Input, MatrixDefault), Pins[0]));	break;
			case ENiagaraDataType::Curve:	Outputs.Add(FNiagaraNodeResult(Compiler->GetInternalConstant(Input, DataObjectDefault), Pins[0]));	break;//Internal curve Constant?
			}
		}
	}
	else
	{
		//This input is an attribute.
		Outputs.Add(FNiagaraNodeResult(Compiler->GetAttribute(Input), Pins[0]));
	}
}