Files
UnrealEngine/Engine/Plugins/PCG/Source/PCG/Public/PCGNode.h
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

268 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "PCGNode.generated.h"
#define UE_API PCG_API
class UPCGNode;
class UPCGPin;
enum class EPCGChangeType : uint32;
enum class EPCGNodeTitleType : uint8;
struct FPCGPinProperties;
class UPCGSettings;
class UPCGSettingsInterface;
class UPCGGraph;
class UPCGEdge;
class IPCGElement;
#if WITH_EDITOR
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPCGNodeChanged, UPCGNode*, EPCGChangeType);
#endif
UCLASS(MinimalAPI, ClassGroup = (Procedural))
class UPCGNode : public UObject
{
GENERATED_BODY()
friend class UPCGGraph;
friend class UPCGEdge;
friend class FPCGGraphCompiler;
public:
UE_API UPCGNode(const FObjectInitializer& ObjectInitializer);
/** ~Begin UObject interface */
UE_API virtual void PostLoad() override;
UE_API virtual void BeginDestroy() override;
#if WITH_EDITOR
UE_API virtual void PreEditUndo() override;
UE_API virtual void PostEditUndo() override;
/** ~End UObject interface */
/** UpdatePins will kick off invalid edges, so this is useful for making pin changes graceful. */
UE_API void ApplyDeprecationBeforeUpdatePins();
/** Used to be able to force deprecation when things need to be deprecated at the graph level. */
UE_API void ApplyDeprecation();
/** If a node does require structural changes, this will apply them */
UE_API virtual void ApplyStructuralDeprecation();
UE_API virtual void RebuildAfterPaste();
#endif
/** Returns the owning graph */
UFUNCTION(BlueprintCallable, Category = Node)
UE_API UPCGGraph* GetGraph() const;
/** Adds an edge in the owning graph to the given "To" node. */
UFUNCTION(BlueprintCallable, Category = Node)
UE_API UPCGNode* AddEdgeTo(FName FromPinLabel, UPCGNode* To, FName ToPinLabel);
/** Removes an edge originating from this node */
UFUNCTION(BlueprintCallable, Category = Node)
UE_API bool RemoveEdgeTo(FName FromPinLable, UPCGNode* To, FName ToPinLabel);
/** Get title for node of specified type. */
UE_API FText GetNodeTitle(EPCGNodeTitleType TitleType) const;
/** Whether user has renamed the node. */
bool HasAuthoredTitle() const { return NodeTitle != NAME_None; }
/** Title to use if no title is authored. */
UE_API FText GetDefaultTitle() const;
/** Authored part of node title (like "Create Constant 1"). */
UE_API FText GetAuthoredTitleLine() const;
/** Authored node title as raw name or none if no title authored. */
FName GetAuthoredTitleName() const { return NodeTitle; }
/** Whether to flip the order of the title lines - display generated title first and authored second. */
UE_API bool HasFlippedTitleLines() const;
/** Generated part of node title, not user editable (like "MyValue = 5.0"). */
UE_API FText GetGeneratedTitleLine() const;
#if WITH_EDITOR
/** Tooltip that describes node functionality and other information. */
UE_API FText GetNodeTooltipText() const;
/** Set the node title. Can be sanitized by the graph/settings if asked. Returns true if the title changed. */
UE_API bool SetNodeTitle(FName NewTitle, bool bApplySanitization = true);
#endif
/** Returns all the input pin properties */
UE_API TArray<FPCGPinProperties> InputPinProperties() const;
/** Returns all the output pin properties */
UE_API TArray<FPCGPinProperties> OutputPinProperties() const;
/** Returns true if the input pin is connected */
UE_API bool IsInputPinConnected(const FName& Label) const;
/** Returns true if the output pin is connected */
UE_API bool IsOutputPinConnected(const FName& Label) const;
/** Returns true if the node has an instance of the settings (e.g. does not own the settings) */
UE_API bool IsInstance() const;
/** Returns the settings interface (settings or instance of settings) on this node */
UPCGSettingsInterface* GetSettingsInterface() const { return SettingsInterface.Get(); }
/** Changes the default settings in the node */
UE_API void SetSettingsInterface(UPCGSettingsInterface* InSettingsInterface, bool bUpdatePins = true);
/** Returns the settings this node holds (either directly or through an instance) */
UFUNCTION(BlueprintCallable, Category = Node)
UE_API UPCGSettings* GetSettings() const;
/** Triggers some uppdates after creating a new node and changing its settings */
UE_API void UpdateAfterSettingsChangeDuringCreation();
UE_API UPCGPin* GetInputPin(const FName& Label);
UE_API const UPCGPin* GetInputPin(const FName& Label) const;
UE_API UPCGPin* GetOutputPin(const FName& Label);
UE_API const UPCGPin* GetOutputPin(const FName& Label) const;
UE_API bool HasInboundEdges() const;
UE_API int32 GetInboundEdgesNum() const;
/** Allow to change the name of a pin, to keep edges connected. You need to make sure that the underlying settings are also updated, otherwise, it will be overwritten next time the settings are updated */
UE_API void RenameInputPin(const FName& InOldLabel, const FName& InNewLabel, bool bInBroadcastUpdate = true);
UE_API void RenameOutputPin(const FName& InOldLabel, const FName& InNewLabel, bool bInBroadcastUpdate = true);
/** Pin from which data is passed through when this node is disabled. */
UE_API virtual const UPCGPin* GetPassThroughInputPin() const;
/** Pin to which data is passed through when this node is disabled. */
UE_API virtual const UPCGPin* GetPassThroughOutputPin() const;
/** A node will be executed (not culled) if at least one required-pin is connected to at least one active upstream pin. */
UE_API virtual bool IsInputPinRequiredByExecution(const UPCGPin* InPin) const;
/** True if the pin is being used by the node. UI will gray out unused pins. */
UE_API virtual bool IsPinUsedByNodeExecution(const UPCGPin* InPin) const;
/** True if the edge is being used by the node. UI will gray out unused pins. */
UE_API virtual bool IsEdgeUsedByNodeExecution(const UPCGEdge* InEdge) const;
/** Returns the first connected input pin on the node. */
UE_API const UPCGPin* GetFirstConnectedInputPin() const;
/** Returns the first connected output pin on the node. */
UE_API const UPCGPin* GetFirstConnectedOutputPin() const;
const TArray<TObjectPtr<UPCGPin>>& GetInputPins() const { return InputPins; }
const TArray<TObjectPtr<UPCGPin>>& GetOutputPins() const { return OutputPins; }
/** Recursively follow downstream edges and call UpdatePins on each node that has dynamic pins. */
UE_API EPCGChangeType PropagateDynamicPinTypes(TSet<UPCGNode*>& TouchedNodes, const UPCGNode* FromNode = nullptr);
#if WITH_EDITOR
/** Transfer all editor only properties to the other node */
UE_API void TransferEditorProperties(UPCGNode* OtherNode) const;
#endif // WITH_EDITOR
#if WITH_EDITOR
UFUNCTION(BlueprintCallable, Category = Node)
UE_API void GetNodePosition(int32& OutPositionX, int32& OutPositionY) const;
UFUNCTION(BlueprintCallable, Category = Node)
UE_API void SetNodePosition(int32 InPositionX, int32 InPositionY);
#endif
#if WITH_EDITORONLY_DATA
UPROPERTY(meta = (PCGNoHash))
TObjectPtr<UPCGSettings> DefaultSettings_DEPRECATED;
#endif
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Node, meta = (PCGNoHash))
FName NodeTitle = NAME_None;
#if WITH_EDITORONLY_DATA
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Node, meta = (PCGNoHash))
FLinearColor NodeTitleColor = FLinearColor::White;
#endif // WITH_EDITORONLY_DATA
#if WITH_EDITOR
FOnPCGNodeChanged OnNodeChangedDelegate;
#endif
#if WITH_EDITORONLY_DATA
UPROPERTY(meta = (PCGNoHash))
int32 PositionX;
UPROPERTY(meta = (PCGNoHash))
int32 PositionY;
UPROPERTY(meta = (PCGNoHash))
FString NodeComment;
UPROPERTY(meta = (PCGNoHash))
uint8 bCommentBubblePinned : 1;
UPROPERTY(meta = (PCGNoHash))
uint8 bCommentBubbleVisible : 1;
private:
/** Will be hidden in the Editor, but will still exist in the backend. Not exposed and mainly used to hide the input/output node. */
UPROPERTY(meta = (PCGNoHash))
uint8 bHidden : 1;
#endif // WITH_EDITORONLY_DATA
public:
#if WITH_EDITOR
bool IsHidden() const { return bHidden;}
#endif // WITH_EDITOR
protected:
/** Updates pins based on node settings. Attempts to migrate pins via matching. Broadcasts node change events for affected nodes. */
UE_API EPCGChangeType UpdatePins();
/** Updates pins based on node settings PinAllocator creates new pin objects. Attempts to migrate pins via matching. Broadcasts node change events for affected nodes. */
UE_API EPCGChangeType UpdatePins(TFunctionRef<UPCGPin* (UPCGNode*)> PinAllocator);
// When we create a new graph, we initialize the input/output nodes as default, with default pins.
// Those default pins are not serialized, therefore if we change the default pins, combined with the use
// of recycling objects in Unreal, can lead to pins that are garbage or even worse: valid pins but not the right
// one, potentially making the edges connecting wrong pins together!
// That is why we have a specific function to create default pins, and we have to make sure that those
// default pins are always created the same way.
UE_API void CreateDefaultPins(TFunctionRef<UPCGPin* (UPCGNode*)> PinAllocator);
#if WITH_EDITOR
UE_API virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
UE_API void OnSettingsChanged(UPCGSettings* InSettings, EPCGChangeType ChangeType);
#endif
/** Note: do not set this property directly from code, use SetSettingsInterface instead */
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = Node)
TObjectPtr<UPCGSettingsInterface> SettingsInterface;
UPROPERTY(meta = (PCGNoHash))
TArray<TObjectPtr<UPCGNode>> OutboundNodes_DEPRECATED;
UPROPERTY(TextExportTransient, meta = (PCGNoHash))
TArray<TObjectPtr<UPCGEdge>> InboundEdges_DEPRECATED;
UPROPERTY(TextExportTransient, meta = (PCGNoHash))
TArray<TObjectPtr<UPCGEdge>> OutboundEdges_DEPRECATED;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = Node)
TArray<TObjectPtr<UPCGPin>> InputPins;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = Node)
TArray<TObjectPtr<UPCGPin>> OutputPins;
// TODO: add this information:
// - Ability to run on non-game threads (here or element)
// - Ability to be multithreaded (here or element)
// - Generates artifacts (here or element)
// - Priority
};
#undef UE_API