Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions Source/Flow/Private/FlowAsset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,8 @@ EDataValidationResult UFlowAsset::ValidateAsset(FFlowMessageLog& MessageLog)
}

Node.Value->ValidationLog.Messages.Empty();
if (Node.Value->ValidateNode() == EDataValidationResult::Invalid)
{
MessageLog.Messages.Append(Node.Value->ValidationLog.Messages);
}
Node.Value->ValidateNode();
MessageLog.Messages.Append(Node.Value->ValidationLog.Messages);
}
else
{
Expand All @@ -134,7 +132,17 @@ EDataValidationResult UFlowAsset::ValidateAsset(FFlowMessageLog& MessageLog)
}
}

return MessageLog.Messages.Num() > 0 ? EDataValidationResult::Invalid : EDataValidationResult::Valid;
// if at least one error has been has been logged : mark the asset as invalid
for (const TSharedRef<FTokenizedMessage>& Msg : MessageLog.Messages)
{
if (Msg->GetSeverity() == EMessageSeverity::Error)
{
return EDataValidationResult::Invalid;
}
}

// otherwise, the asset is considered valid (even with warnings or notes)
return EDataValidationResult::Valid;
}

bool UFlowAsset::IsNodeOrAddOnClassAllowed(const UClass* FlowNodeOrAddOnClass, FText* OutOptionalFailureReason) const
Expand Down
31 changes: 31 additions & 0 deletions Source/Flow/Private/Nodes/FlowNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,39 @@ void UFlowNode::PostLoad()
FixNode(nullptr);
}

EDataValidationResult UFlowNode::ValidateNode()
{
if (GetClass()->IsFunctionImplementedInScript(GET_FUNCTION_NAME_CHECKED(UFlowNode, K2_ValidateNode)))
{
return K2_ValidateNode();
}

return EDataValidationResult::NotValidated;
}

#endif

void UFlowNode::LogValidationError(const FString& Message)
{
#if WITH_EDITOR
ValidationLog.Error<UFlowNode>(*Message, this);
#endif
}

void UFlowNode::LogValidationWarning(const FString& Message)
{
#if WITH_EDITOR
ValidationLog.Warning<UFlowNode>(*Message, this);
#endif
}

void UFlowNode::LogValidationNote(const FString& Message)
{
#if WITH_EDITOR
ValidationLog.Note<UFlowNode>(*Message, this);
#endif
}

bool UFlowNode::IsSupportedInputPinName(const FName& PinName) const
{
const FFlowPin* InputPin = FindFlowPinByName(PinName, InputPins);
Expand Down
22 changes: 20 additions & 2 deletions Source/Flow/Public/Nodes/FlowNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,28 @@ class FLOW_API UFlowNode
virtual void PostLoad() override;
// --

virtual EDataValidationResult ValidateNode() { return EDataValidationResult::NotValidated; }

virtual EDataValidationResult ValidateNode();
#endif

// Flow Node Validation : blueprint compatibility

// Optional validation override for Blueprints
UFUNCTION(BlueprintImplementableEvent, Category = "FlowNode|Validation", meta = (DisplayName = "Validate Node"))
EDataValidationResult K2_ValidateNode();

// Log validation error (editor-only)
UFUNCTION(BlueprintCallable, Category = "FlowNode|Validation")
Copy link
Contributor

@MaksymKapelianovych MaksymKapelianovych Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add meta = (DevelopmentOnly) to these functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done !

void LogValidationError(const FString& Message);

// Log validation warning (editor-only)
UFUNCTION(BlueprintCallable, Category = "FlowNode|Validation")
void LogValidationWarning(const FString& Message);

// Log validation note (editor-only)
UFUNCTION(BlueprintCallable, Category = "FlowNode|Validation")
void LogValidationNote(const FString& Message);
// --

// Inherits Guid after graph node
UPROPERTY()
FGuid NodeGuid;
Expand Down