Files
Andron666 9c38e93fa4 part7
2022-12-05 20:31:35 +05:00

892 lines
30 KiB
C++

/*
* 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<UHoudiniOutput*>& InUpdatedOutputs) { ResultOutputs = InUpdatedOutputs; }
// Getter for ResultOutputs
TArray<UHoudiniOutput*>& GetResultOutputs() { return ResultOutputs; }
// Getter for ResultOutputs
const TArray<UHoudiniOutput*>& 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<UObject*> ResultObjects;
UPROPERTY(NonTransactional)
TArray<UHoudiniOutput*> 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<UObject*> 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<FTOPWorkResultObject> ResultObjects;
/*
UPROPERTY()
TArray<UObject*> ResultObjects;
UPROPERTY()
TArray<FString> ResultNames;
UPROPERTY()
TArray<FString> ResultFilePaths;
UPROPERTY()
TArray<EPDGWorkResultState> 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<int32> AllWorkItems;
UPROPERTY()
TSet<int32> WaitingWorkItems;
UPROPERTY()
TSet<int32> ScheduledWorkItems;
UPROPERTY()
TSet<int32> CookingWorkItems;
UPROPERTY()
TSet<int32> CookedWorkItems;
UPROPERTY()
TSet<int32> ErroredWorkItems;
UPROPERTY()
TSet<int32> 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<FHoudiniBakedOutput> 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<FString, FHoudiniPDGWorkResultObjectBakedOutput>& GetBakedWorkResultObjectsOutputs() { return BakedWorkResultObjectOutputs; }
const TMap<FString, FHoudiniPDGWorkResultObjectBakedOutput>& 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<FTOPWorkResult> 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<FString> 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<FString, FHoudiniPDGWorkResultObjectBakedOutput> 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<UTOPNode*> 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<UTOPNode*>& InTOPNodes, int32& OutIndex);
// Find the network with relative path 'InNetPath' from the HDA
static UTOPNetwork* GetTOPNetworkByNodePath(const FString& InNodePath, const TArray<UTOPNetwork*>& 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<UTOPNetwork*> 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
};