/* * Copyright (c) <2021> Side Effects Software Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. The name of Side Effects Software may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once //#include "CoreMinimal.h" #include "UObject/ObjectMacros.h" #include "HoudiniAsset.h" #include "HoudiniAssetComponent.h" #include "HoudiniTranslatorTypes.h" #include "HoudiniPDGAssetLink.generated.h" struct FHoudiniPackageParams; UENUM() enum class EPDGLinkState : uint8 { Inactive, Linking, Linked, Error_Not_Linked }; UENUM() enum class EPDGNodeState : uint8 { None, Dirtied, Dirtying, Cooking, Cook_Complete, Cook_Failed }; UENUM() enum class EPDGWorkResultState : uint8 { None, ToLoad, Loading, Loaded, ToDelete, Deleting, Deleted, NotLoaded }; USTRUCT() struct HOUDINIENGINERUNTIME_API FOutputActorOwner { GENERATED_BODY(); public: FOutputActorOwner() : OutputActor(nullptr) {}; virtual ~FOutputActorOwner() {}; // Create OutputActor, an actor to hold work result output virtual bool CreateOutputActor(UWorld* InWorld, UHoudiniPDGAssetLink* InAssetLink, AActor *InParentActor, const FName& InName); // Return OutputActor virtual AActor* GetOutputActor() const { return OutputActor; } // Setter for OutputActor virtual void SetOutputActor(AActor* InActor) { OutputActor = InActor; } // Destroy OutputActor if it is valid. virtual bool DestroyOutputActor(); private: UPROPERTY(NonTransactional) AActor* OutputActor; }; USTRUCT() struct HOUDINIENGINERUNTIME_API FTOPWorkResultObject { GENERATED_USTRUCT_BODY() public: // Constructor FTOPWorkResultObject(); // Call DestroyResultObjects in the destructor virtual ~FTOPWorkResultObject(); // Set ResultObjects to a copy of InUpdatedOutputs void SetResultOutputs(const TArray& InUpdatedOutputs) { ResultOutputs = InUpdatedOutputs; } // Getter for ResultOutputs TArray& GetResultOutputs() { return ResultOutputs; } // Getter for ResultOutputs const TArray& GetResultOutputs() const { return ResultOutputs; } // Destroy ResultOutputs void DestroyResultOutputs(); // Get the OutputActor owner struct FOutputActorOwner& GetOutputActorOwner() { return OutputActorOwner; } // Get the OutputActor owner struct const FOutputActorOwner& GetOutputActorOwner() const { return OutputActorOwner; } // Destroy the ResultOutputs and remove the output actor. void DestroyResultOutputsAndRemoveOutputActor(); // Getter for bAutoBakedSinceLastLoad: indicates if this work result object has been auto-baked since it's last load. bool AutoBakedSinceLastLoad() const { return bAutoBakedSinceLastLoad; } // Setter for bAutoBakedSinceLastLoad void SetAutoBakedSinceLastLoad(bool bInAutoBakedSinceLastLoad) { bAutoBakedSinceLastLoad = bInAutoBakedSinceLastLoad; } public: UPROPERTY(NonTransactional) FString Name; UPROPERTY(NonTransactional) FString FilePath; UPROPERTY(NonTransactional) EPDGWorkResultState State; // The index in the WorkItemResultInfo array of this item as it was received from HAPI. UPROPERTY(NonTransactional) int32 WorkItemResultInfoIndex; protected: // UPROPERTY() // TArray ResultObjects; UPROPERTY(NonTransactional) TArray ResultOutputs; // If true, indicates that the work result object has been auto-baked since it was last loaded. UPROPERTY(NonTransactional) bool bAutoBakedSinceLastLoad = false; private: // List of objects to delete, internal use only (DestroyResultOutputs) UPROPERTY(NonTransactional) TArray OutputObjectsToDelete; UPROPERTY(NonTransactional) FOutputActorOwner OutputActorOwner; }; USTRUCT() struct HOUDINIENGINERUNTIME_API FTOPWorkResult { GENERATED_USTRUCT_BODY() public: // Constructor FTOPWorkResult(); // Comparison operator, used by hashing containers and arrays. bool operator==(const FTOPWorkResult& OtherWorkResult) const; // Calls FTOPWorkResultObject::DestroyResultOutputsAndRemoveOutputActor on each entry in ResultObjects and clears the array. void ClearAndDestroyResultObjects(); // Search for the first FTOPWorkResultObject entry by WorkItemResultInfoIndex and return it, or nullptr if it could not be found. int32 IndexOfWorkResultObjectByHAPIResultInfoIndex(const int32& InWorkItemResultInfoIndex); // Search for the first FTOPWorkResultObject entry by WorkItemResultInfoIndex and return it, or nullptr if it could not be found. FTOPWorkResultObject* GetWorkResultObjectByHAPIResultInfoIndex(const int32& InWorkItemResultInfoIndex); // Return the FTOPWorkResultObject at InArrayIndex in the ResultObjects array, or nullptr if InArrayIndex is not a valid index. FTOPWorkResultObject* GetWorkResultObjectByArrayIndex(const int32& InArrayIndex); public: UPROPERTY(NonTransactional) int32 WorkItemIndex; UPROPERTY(Transient) int32 WorkItemID; UPROPERTY(NonTransactional) TArray ResultObjects; /* UPROPERTY() TArray ResultObjects; UPROPERTY() TArray ResultNames; UPROPERTY() TArray ResultFilePaths; UPROPERTY() TArray ResultStates; */ }; USTRUCT() struct HOUDINIENGINERUNTIME_API FWorkItemTallyBase { GENERATED_USTRUCT_BODY() public: virtual ~FWorkItemTallyBase(); // // Mutators // // Zero all counts, including total. virtual void ZeroAll() {}; // // Accessors // bool AreAllWorkItemsComplete() const; bool AnyWorkItemsFailed() const; bool AnyWorkItemsPending() const; virtual int32 NumWorkItems() const { return 0; }; virtual int32 NumWaitingWorkItems() const { return 0; }; virtual int32 NumScheduledWorkItems() const { return 0; }; virtual int32 NumCookingWorkItems() const { return 0; }; virtual int32 NumCookedWorkItems() const { return 0; }; virtual int32 NumErroredWorkItems() const { return 0; }; virtual int32 NumCookCancelledWorkItems() const { return 0; }; FString ProgressRatio() const; }; USTRUCT() struct HOUDINIENGINERUNTIME_API FWorkItemTally : public FWorkItemTallyBase { GENERATED_USTRUCT_BODY() public: // Constructor FWorkItemTally(); // // Mutators // // Empty all state sets, as well as AllWorkItems. virtual void ZeroAll() override; // Remove a work item from all state sets and AllWorkItems. void RemoveWorkItem(int32 InWorkItemID); void RecordWorkItemAsWaiting(int32 InWorkItemID); void RecordWorkItemAsScheduled(int32 InWorkItemID); void RecordWorkItemAsCooking(int32 InWorkItemID); void RecordWorkItemAsCooked(int32 InWorkItemID); void RecordWorkItemAsErrored(int32 InWorkItemID); void RecordWorkItemAsCookCancelled(int32 InWorkItemID); // // Accessors // virtual int32 NumWorkItems() const override { return AllWorkItems.Num(); } virtual int32 NumWaitingWorkItems() const override { return WaitingWorkItems.Num(); } virtual int32 NumScheduledWorkItems() const override { return ScheduledWorkItems.Num(); } virtual int32 NumCookingWorkItems() const override { return CookingWorkItems.Num(); } virtual int32 NumCookedWorkItems() const override { return CookedWorkItems.Num(); } virtual int32 NumErroredWorkItems() const override { return ErroredWorkItems.Num(); } virtual int32 NumCookCancelledWorkItems() const override { return CookCancelledWorkItems.Num(); } protected: // Removes the work item id from all state sets (but not from AllWorkItems -- use RemoveWorkItem for that). void RemoveWorkItemFromAllStateSets(int32 InWorkItemID); // We use sets to keep track of in what state a work item is. The set stores the WorkItemID. UPROPERTY() TSet AllWorkItems; UPROPERTY() TSet WaitingWorkItems; UPROPERTY() TSet ScheduledWorkItems; UPROPERTY() TSet CookingWorkItems; UPROPERTY() TSet CookedWorkItems; UPROPERTY() TSet ErroredWorkItems; UPROPERTY() TSet CookCancelledWorkItems; }; USTRUCT() struct HOUDINIENGINERUNTIME_API FAggregatedWorkItemTally : public FWorkItemTallyBase { GENERATED_USTRUCT_BODY() public: // Constructor FAggregatedWorkItemTally(); virtual void ZeroAll() override; void Add(const FWorkItemTallyBase& InWorkItemTally); void Subtract(const FWorkItemTallyBase& InWorkItemTally); virtual int32 NumWorkItems() const override { return TotalWorkItems; } virtual int32 NumWaitingWorkItems() const override { return WaitingWorkItems; } virtual int32 NumScheduledWorkItems() const override { return ScheduledWorkItems; } virtual int32 NumCookingWorkItems() const override { return CookingWorkItems; } virtual int32 NumCookedWorkItems() const override { return CookedWorkItems; } virtual int32 NumErroredWorkItems() const override { return ErroredWorkItems; } protected: UPROPERTY() int32 TotalWorkItems; UPROPERTY() int32 WaitingWorkItems; UPROPERTY() int32 ScheduledWorkItems; UPROPERTY() int32 CookingWorkItems; UPROPERTY() int32 CookedWorkItems; UPROPERTY() int32 ErroredWorkItems; UPROPERTY() int32 CookCancelledWorkItems; }; // Container for baked outputs of a PDG work result object. USTRUCT() struct HOUDINIENGINERUNTIME_API FHoudiniPDGWorkResultObjectBakedOutput { GENERATED_BODY() public: // Array of baked output per output index of the work result object's outputs. UPROPERTY() TArray BakedOutputs; }; // Forward declare the UTOPNetwork here for some references in the UTOPNode class UTOPNetwork; UCLASS() class HOUDINIENGINERUNTIME_API UTOPNode : public UObject { GENERATED_BODY() public: // Constructor UTOPNode(); // Comparison operator, used by hashing containers and arrays. bool operator==(const UTOPNode& Other) const; void Reset(); const FWorkItemTallyBase& GetWorkItemTally() const { if (bHasChildNodes) return AggregatedWorkItemTally; return WorkItemTally; } void AggregateTallyFromChildNode(const UTOPNode* InChildNode) { if (IsValid(InChildNode)) AggregatedWorkItemTally.Add(InChildNode->GetWorkItemTally()); } bool AreAllWorkItemsComplete() const { return GetWorkItemTally().AreAllWorkItemsComplete(); }; bool AnyWorkItemsFailed() const { return GetWorkItemTally().AnyWorkItemsFailed(); }; bool AnyWorkItemsPending() const { return GetWorkItemTally().AnyWorkItemsPending(); }; void ZeroWorkItemTally() { WorkItemTally.ZeroAll(); AggregatedWorkItemTally.ZeroAll(); } // Called by PDG manager when work item events are received // Notification that a work item has been created void OnWorkItemCreated(int32 InWorkItemID) { }; // Notification that a work item has been removed. void OnWorkItemRemoved(int32 InWorkItemID) { WorkItemTally.RemoveWorkItem(InWorkItemID); }; // Notification that a work item has moved to the waiting state. void OnWorkItemWaiting(int32 InWorkItemID); // Notification that a work item has been scheduled. void OnWorkItemScheduled(int32 InWorkItemID) { WorkItemTally.RecordWorkItemAsScheduled(InWorkItemID); }; // Notification that a work item has started cooking. void OnWorkItemCooking(int32 InWorkItemID) { WorkItemTally.RecordWorkItemAsCooking(InWorkItemID); }; // Notification that a work item has been cooked. void OnWorkItemCooked(int32 InWorkItemID); // Notification that a work item has errored. void OnWorkItemErrored(int32 InWorkItemID) { WorkItemTally.RecordWorkItemAsErrored(InWorkItemID); }; // Notification that a work item cook has been cancelled. void OnWorkItemCookCancelled(int32 InWorkItemID) { WorkItemTally.RecordWorkItemAsCookCancelled(InWorkItemID); }; bool IsVisibleInLevel() const { return bShow; } void SetVisibleInLevel(bool bInVisible); void UpdateOutputVisibilityInLevel(); // Sets all WorkResultObjects that are in the NotLoaded state to ToLoad. void SetNotLoadedWorkResultsToLoad(bool bInAlsoSetDeletedToLoad=false); // Sets all WorkResultObjects that are in the Loaded state to ToDelete (will delete output objects and output // actors). void SetLoadedWorkResultsToDelete(); // Immediately delete Loaded work result output objects (keeps the work items and result arrays but deletes the output // objects and actors and sets the state to Deleted. void DeleteWorkResultOutputObjects(); // Get the OutputActor owner struct FOutputActorOwner& GetOutputActorOwner() { return OutputActorOwner; } // Get the OutputActor owner struct const FOutputActorOwner& GetOutputActorOwner() const { return OutputActorOwner; } // Get the baked outputs from the last bake. The map keys are [work_result.work_item_index]_[work_result_object_index] TMap& GetBakedWorkResultObjectsOutputs() { return BakedWorkResultObjectOutputs; } const TMap& GetBakedWorkResultObjectsOutputs() const { return BakedWorkResultObjectOutputs; } // Helper to construct the key used to look up baked work results. static FString GetBakedWorkResultObjectOutputsKey(int32 InWorkItemIndex, int32 InWorkResultObjectArrayIndex); // Helper to construct the key used to look up baked work results. static FString GetBakedWorkResultObjectOutputsKey(const FTOPWorkResult& InWorkResult, int32 InWorkResultObjectArrayIndex); // Helper to construct the key used to look up baked work results. bool GetBakedWorkResultObjectOutputsKey(int32 InWorkResultArrayIndex, int32 InWorkResultObjectArrayIndex, FString& OutKey) const; // Get the FHoudiniPDGWorkResultObjectBakedOutput for a work item (FTOPWorkResult) and specific result object. bool GetBakedWorkResultObjectOutputs(int32 InWorkResultArrayIndex, int32 InWorkResultObjectArrayIndex, FHoudiniPDGWorkResultObjectBakedOutput*& OutBakedOutput); // Get the FHoudiniPDGWorkResultObjectBakedOutput for a work item (FTOPWorkResult) and specific result object (const version). bool GetBakedWorkResultObjectOutputs(int32 InWorkResultArrayIndex, int32 InWorkResultObjectArrayIndex, FHoudiniPDGWorkResultObjectBakedOutput const*& OutBakedOutput) const; // Search for the first FTOPWorkResult entry by WorkItemID and return it, or nullptr if it could not be found. int32 IndexOfWorkResultByID(const int32& InWorkItemID); // Search for the first FTOPWorkResult entry by WorkItemID and return it, or nullptr if it could not be found. FTOPWorkResult* GetWorkResultByID(const int32& InWorkItemID); // Search for the first FTOPWorkResult entry by WorkItemIndex and return it, or nullptr if it could not be found. // If bWithInvalidWorkItemID is true, then only return an entry if its WorkItemID is INDEX_NONE. int32 IndexOfWorkResultByHAPIIndex(const int32& InWorkItemIndex, bool bInWithInvalidWorkItemID=false); // Search for the first FTOPWorkResult entry by WorkItemIndex and return it, or nullptr if it could not be found. // If bWithInvalidWorkItemID is true, then only return an entry if its WorkItemID is INDEX_NONE. FTOPWorkResult* GetWorkResultByHAPIIndex(const int32& InWorkItemIndex, bool bInWithInvalidWorkItemID=false); // Return the FTOPWorkResult at InArrayIndex in the WorkResult array, or nullptr if InArrayIndex is not a valid index. FTOPWorkResult* GetWorkResultByArrayIndex(const int32& InArrayIndex); // Returns true if InNetwork is the parent TOP Net of this node. bool IsParentTOPNetwork(UTOPNetwork const * const InNetwork) const; // Returns true if this node can still be auto-baked bool CanStillBeAutoBaked() const; #if WITH_EDITOR void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override; #endif #if WITH_EDITOR void PostTransacted(const FTransactionObjectEvent& TransactionEvent) override; #endif public: UPROPERTY(Transient, NonTransactional) int32 NodeId; UPROPERTY(NonTransactional) FString NodeName; UPROPERTY(NonTransactional) FString NodePath; UPROPERTY(NonTransactional) FString ParentName; UPROPERTY() UObject* WorkResultParent; UPROPERTY(NonTransactional) TArray WorkResult; // Hidden in the nodes combobox UPROPERTY() bool bHidden; UPROPERTY() bool bAutoLoad; UPROPERTY(Transient, NonTransactional) EPDGNodeState NodeState; // This is set when the TOP node's work items are processed by // FHoudiniPDGManager based on if any NotLoaded work result objects are found UPROPERTY(NonTransactional) bool bCachedHaveNotLoadedWorkResults; // This is set when the TOP node's work items are processed by // FHoudiniPDGManager based on if any Loaded work result objects are found UPROPERTY(NonTransactional) bool bCachedHaveLoadedWorkResults; // True if this node has child nodes UPROPERTY(NonTransactional) bool bHasChildNodes; // These notification events have been introduced so that we can start encapsulating code. // in this class as opposed to modifying this object in various places throughout the codebase. // Notification that this TOP node has been dirtied. void OnDirtyNode(); // Accessors for the landscape data caches FHoudiniLandscapeExtent& GetLandscapeExtent() { return LandscapeExtent; } FHoudiniLandscapeReferenceLocation& GetLandscapeReferenceLocation() { return LandscapeReferenceLocation; } FHoudiniLandscapeTileSizeInfo& GetLandscapeSizeInfo() { return LandscapeSizeInfo; } // More cached landscape data UPROPERTY() TSet ClearedLandscapeLayers; // Returns true if the node has received the HAPI_PDG_EVENT_COOK_COMPLETE event since the last the cook started bool HasReceivedCookCompleteEvent() const { return bHasReceivedCookCompleteEvent; } // Handler for when the node receives the HAPI_PDG_EVENT_COOK_START (called for each node when a TOPNet starts cooking) void HandleOnPDGEventCookStart() { bHasReceivedCookCompleteEvent = false; } // Handler for when the node receives the HAPI_PDG_EVENT_COOK_COMPLETE event (called for each node when a TOPNet completes cooking) void HandleOnPDGEventCookComplete() { bHasReceivedCookCompleteEvent = true; } protected: void InvalidateLandscapeCache(); // Value caches used during landscape tile creation. FHoudiniLandscapeReferenceLocation LandscapeReferenceLocation; FHoudiniLandscapeTileSizeInfo LandscapeSizeInfo; FHoudiniLandscapeExtent LandscapeExtent; // Visible in the level UPROPERTY() bool bShow; // Map of [work_result_index]_[work_result_object_index] to the work result object's baked outputs. UPROPERTY() TMap BakedWorkResultObjectOutputs; // This node's own work items, used when bHasChildNodes is false. UPROPERTY(Transient, NonTransactional) FWorkItemTally WorkItemTally; // This node's aggregated work item tallys (sum of child work item tally, use when bHasChildNodes is true) UPROPERTY(Transient, NonTransactional) FAggregatedWorkItemTally AggregatedWorkItemTally; // Set to true when the node recieves HAPI_PDG_EVENT_COOK_COMPLETE event UPROPERTY(Transient, NonTransactional) bool bHasReceivedCookCompleteEvent; private: UPROPERTY() FOutputActorOwner OutputActorOwner; }; UCLASS() class HOUDINIENGINERUNTIME_API UTOPNetwork : public UObject { GENERATED_BODY() public: // Delegate that is broadcast when cook of the network is complete. Parameters are the UTOPNetwork and bAnyFailedWorkItems. DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPostCookDelegate, UTOPNetwork*, const bool); // Constructor UTOPNetwork(); // Comparison operator, used by hashing containers and arrays. bool operator==(const UTOPNetwork& Other) const; // Sets all WorkResultObjects that are in the Loaded state to ToDelete (will delete output objects and output // actors). void SetLoadedWorkResultsToDelete(); // Immediately delete Loaded work result output objects (keeps the work items and result arrays but deletes the output // objects and actors and sets the state to Deleted. void DeleteWorkResultOutputObjects(); // Returns true if any node in this TOP net has pending (waiting, scheduled, cooking) work items. bool AnyWorkItemsPending() const; // Returns true if any node in this TOP net has failed/errored work items. bool AnyWorkItemsFailed() const; // Returns true if this network has nodes that can still be auto-baked bool CanStillBeAutoBaked() const; // Handler for when a node in the newtork receives the HAPI_PDG_EVENT_COOK_COMPLETE event (called for each node when a TOPNet completes cooking) void HandleOnPDGEventCookCompleteReceivedByChildNode(UHoudiniPDGAssetLink* const InAssetLink, UTOPNode* const InTOPNode); FOnPostCookDelegate& GetOnPostCookDelegate() { return OnPostCookDelegate; } public: UPROPERTY(Transient, NonTransactional) int32 NodeId; UPROPERTY(NonTransactional) FString NodeName; // HAPI path to this node (relative to the HDA) UPROPERTY(NonTransactional) FString NodePath; UPROPERTY() TArray AllTOPNodes; // TODO: Should be using SelectedNodeName instead? // Index is not consistent after updating filter UPROPERTY() int32 SelectedTOPIndex; UPROPERTY(NonTransactional) FString ParentName; UPROPERTY() bool bShowResults; UPROPERTY() bool bAutoLoadResults; FOnPostCookDelegate OnPostCookDelegate; }; class UHoudiniPDGAssetLink; DECLARE_MULTICAST_DELEGATE_FourParams(FHoudiniPDGAssetLinkWorkResultObjectLoaded, UHoudiniPDGAssetLink*, UTOPNode*, int32 /*WorkItemHAPIIndex*/, int32 /*WorkItemResultInfoIndex*/); UCLASS() class HOUDINIENGINERUNTIME_API UHoudiniPDGAssetLink : public UObject { GENERATED_UCLASS_BODY() public: friend class UHoudiniAssetComponent; // Delegate for when the entire bake operation is complete (all selected nodes/networks have been baked). DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPostBakeDelegate, UHoudiniPDGAssetLink*, const bool); // Delegate for when a network completes a cook. Passes the asset link, the network, a bAnyWorkItemsFailed. DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnPostTOPNetworkCookDelegate, UHoudiniPDGAssetLink*, UTOPNetwork*, const bool); static FString GetAssetLinkStatus(const EPDGLinkState& InLinkState); static FString GetTOPNodeStatus(const UTOPNode* InTOPNode); static FLinearColor GetTOPNodeStatusColor(const UTOPNode* InTOPNode); void UpdateTOPNodeWithChildrenWorkItemTallyAndState(UTOPNode* InNode, UTOPNetwork* InNetwork); void UpdateWorkItemTally(); static void ResetTOPNetworkWorkItemTally(UTOPNetwork* TOPNetwork); // Set the TOP network at the given index as currently selected TOP network void SelectTOPNetwork(const int32& AtIndex); // Set the TOP node at the given index in the given TOP network as currently selected TOP node void SelectTOPNode(UTOPNetwork* InTOPNetwork, const int32& AtIndex); UTOPNode* GetSelectedTOPNode(); const UTOPNode* GetSelectedTOPNode() const; UTOPNetwork* GetSelectedTOPNetwork(); const UTOPNetwork* GetSelectedTOPNetwork() const; FString GetSelectedTOPNodeName(); FString GetSelectedTOPNetworkName(); UTOPNode* GetTOPNode(const int32& InNodeID); bool GetTOPNodeAndNetworkByNodeId(const int32& InNodeID, UTOPNetwork*& OutNetwork, UTOPNode*& OutNode); UTOPNetwork* GetTOPNetwork(const int32& AtIndex); const UTOPNetwork* GetTOPNetwork(const int32& AtIndex) const; // Find the node with relative path 'InNodePath' from its topnet. static UTOPNode* GetTOPNodeByNodePath(const FString& InNodePath, const TArray& InTOPNodes, int32& OutIndex); // Find the network with relative path 'InNetPath' from the HDA static UTOPNetwork* GetTOPNetworkByNodePath(const FString& InNodePath, const TArray& InTOPNetworks, int32& OutIndex); // Get the parent TOP node of the specified node. This is resolved UTOPNode* GetParentTOPNode(const UTOPNode* InNode); static void ClearTOPNodeWorkItemResults(UTOPNode* TOPNode); static void ClearTOPNetworkWorkItemResults(UTOPNetwork* TOPNetwork); // Clear the result objects of a work item (FTOPWorkResult.ResultObjects), but don't delete the work item from // TOPNode.WorkResults (for example, the work item was dirtied but not removed from PDG) static void ClearWorkItemResultByID(const int32& InWorkItemID, UTOPNode* InTOPNode); // Calls ClearWorkItemResultByID and then deletes the FTOPWorkResult from InTOPNode.Result as well. For example: // the work item was removed in PDG. static void DestroyWorkItemByID(const int32& InWorkItemID, UTOPNode* InTOPNode); static FTOPWorkResult* GetWorkResultByID(const int32& InWorkItemID, UTOPNode* InTOPNode); // This should be called after the owner and this PDG asset link is duplicated. Set all output parent actors to // null in all TOP networks/nodes. Since the TOP Networks/TOP nodes are all structs, we cannot set // DuplicateTransient property on their OutputActor properties. void UpdatePostDuplicate(); // Load the geometry generated as results of the given work item, of the given TOP node. // The load will be done asynchronously. // Results must be tagged with 'file', and must have a file path, otherwise will not be loaded. //void LoadResults(FTOPNode TOPNode, HAPI_PDG_WorkitemInfo workItemInfo, HAPI_PDG_WorkitemResultInfo[] resultInfos, HAPI_PDG_WorkitemId workItemID) // Return the first UHoudiniAssetComponent in the parent chain. If this asset link is not // owned by a HoudiniAssetComponent, a nullptr will be returned. UHoudiniAssetComponent* GetOuterHoudiniAssetComponent() const; // Gets the temporary cook folder. If the parent of this asset link is a HoudiniAssetComponent use that, otherwise // use the default static mesh temporary cook folder. FDirectoryPath GetTemporaryCookFolder() const; // Get the actor that owns this PDG asset link. If the asset link is owned by a component, // then the component's owning actor is returned. Can return null if this is now owned by // an actor or component. AActor* GetOwnerActor() const; // Checks if the asset link has any temporary outputs and returns true if it has bool HasTemporaryOutputs() const; // Filter TOP nodes and outputs (hidden/visible) by TOPNodeFilter and TOPOutputFilter. void FilterTOPNodesAndOutputs(); // On all FTOPNodes: Load not loaded items if bAutoload is true, and update the level visibility of work items // result. Used when FTOPNode.bShow and/or FTOPNode.bAutoload changed. void UpdateTOPNodeAutoloadAndVisibility(); #if WITH_EDITORONLY_DATA // Returns true if there are any nodes left that can/must still be auto-baked. bool AnyRemainingAutoBakeNodes() const; #endif // Delegate handlers // Get the post bake delegate FOnPostBakeDelegate& GetOnPostBakeDelegate() { return OnPostBakeDelegate; } // Called by baking code after baking all of the outputs void HandleOnPostBake(const bool bInSuccess); FOnPostTOPNetworkCookDelegate& GetOnPostTOPNetworkCookDelegate() { return OnPostTOPNetworkCookDelegate; } // Handler for when a TOP network completes a cook. Called by the TOP Net once all of its nodes have received // HAPI_PDG_EVENT_COOK_COMPLETE. void HandleOnTOPNetworkCookComplete(UTOPNetwork* const InTOPNet); #if WITH_EDITORONLY_DATA void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override; #endif #if WITH_EDITORONLY_DATA void PostTransacted(const FTransactionObjectEvent& TransactionEvent) override; #endif private: void ClearAllTOPData(); static void DestroyWorkItemResultData(FTOPWorkResult& Result); static void DestoryWorkResultObjectData(FTOPWorkResultObject& ResultObject); public: //UPROPERTY() //UHoudiniAsset* HoudiniAsset; //UPROPERTY() //UHoudiniAssetComponent* ParentHAC; UPROPERTY(DuplicateTransient, NonTransactional) FString AssetName; // The full path to the HDA in HAPI UPROPERTY(DuplicateTransient, NonTransactional) FString AssetNodePath; UPROPERTY(DuplicateTransient, NonTransactional) int32 AssetID; UPROPERTY() TArray AllTOPNetworks; UPROPERTY() int32 SelectedTOPNetworkIndex; UPROPERTY(Transient, NonTransactional) EPDGLinkState LinkState; UPROPERTY() bool bAutoCook; UPROPERTY() bool bUseTOPNodeFilter; UPROPERTY() bool bUseTOPOutputFilter; UPROPERTY() FString TOPNodeFilter; UPROPERTY() FString TOPOutputFilter; UPROPERTY(NonTransactional) int32 NumWorkitems; UPROPERTY(Transient, NonTransactional) FAggregatedWorkItemTally WorkItemTally; UPROPERTY() FString OutputCachePath; UPROPERTY(Transient) bool bNeedsUIRefresh; // A parent actor to serve as the parent of any output actors // that are created. // If null, then output actors are created under a folder UPROPERTY(EditAnywhere, Category="Output") AActor* OutputParentActor; // Folder used for baking PDG outputs UPROPERTY() FDirectoryPath BakeFolder; // // Notifications // // Delegate that is broadcast when a work result object has been loaded FHoudiniPDGAssetLinkWorkResultObjectLoaded OnWorkResultObjectLoaded; // Delegate that is broadcast after a bake. FOnPostBakeDelegate OnPostBakeDelegate; // Delegate that is broadcast after a TOP Network completes a cook. FOnPostTOPNetworkCookDelegate OnPostTOPNetworkCookDelegate; // // End: Notifications // #if WITH_EDITORONLY_DATA UPROPERTY() bool bBakeMenuExpanded; // What kind of output to bake, for example, bake actors, bake to blueprint UPROPERTY() EHoudiniEngineBakeOption HoudiniEngineBakeOption; // Which outputs to bake, for example, all, selected network, selected node UPROPERTY() EPDGBakeSelectionOption PDGBakeSelectionOption; // This determines if the baked assets should replace existing assets with the same name, // or always generate new assets (with numerical suffixes if needed to create unique names) UPROPERTY() EPDGBakePackageReplaceModeOption PDGBakePackageReplaceMode; // If true, recenter baked actors to their bounding box center after bake UPROPERTY() bool bRecenterBakedActors; // Auto-bake: if this is true, it indicates that once all work result objects for the node is loaded they should // all be baked UPROPERTY() bool bBakeAfterAllWorkResultObjectsLoaded; // The delegate handle of the auto bake helper function bound to OnWorkResultObjectLoaded. FDelegateHandle AutoBakeDelegateHandle; #endif };