You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Per-node constant data is now held on a generated struct as part of sparse class data. Per-node mutable data (i.e. pin links/property access mappings) is now held on a generated 'mutable data' struct that is compiled as part of the generated class. The anim BP compiler is now extended more conventionally using UAnimBlueprintExtension, derived from UBlueprintExtension. This directly replaces the older 'compiler handler' pattern that was added in an emergency fashion for 4.26. Anim graph nodes now request their required extensions and these are held on the UAnimBlueprint in the UBlueprint::Extensions array. The Extensions array is potentially refreshed with any node addition or removal. The Extensions array is force-refreshed each time an anim BP is compiled for the first time to deal with newly added or removed requirements. Const-corrected a bunch of UAnimInstance/FAnimInstanceProxy APIs that rely on (now truly) const data. Added a split state/constant version of FInputScaleBiasClamp to allow some of its data to be split into constants. Tweaked alignment/ordering of FPoseLinkBase to save a few bytes per pose link. Deprecated FAnimNode_Base::OverrideAsset in favor of a more UAnimGraphNode_Base-based approach. Individual nodes can still have runtime overrides via specific accessors. The new approach will also give us the oppurtunity to override multiple assets per node if required in the future. Moved property access into Engine module & removed event support from it - this was never used. Reworked property access compilation API a little - construction/lifetime was a bit confusing previously. Optimized path used to create UK2Node_StructMemberSet nodes in per-node custom events. When using mutable data, the structure used is large and very sparsely connected (i.e. only a few properties are written) so we only create pins that are actually going to be used, rather than creating all of them and conly connecting a few. Patched the following nodes to use the new data approach: - Asset players (sequences, blendspaces, aim offsets) - Blend lists - Ref poses - Roots #rb Jurre.deBaare, Martin.Wilson, Keith.Yerex [CL 16090510 by Thomas Sarkanen in ue5-main branch]
254 lines
8.9 KiB
C++
254 lines
8.9 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "AnimBlueprintExtension.h"
|
|
#include "AnimBlueprintExtension_PropertyAccess.h"
|
|
#include "Animation/AnimNodeBase.h"
|
|
#include "IPropertyAccessCompiler.h"
|
|
#include "Animation/AnimSubsystem_Base.h"
|
|
#include "AnimBlueprintExtension_Base.generated.h"
|
|
|
|
class UAnimGraphNode_Base;
|
|
struct FAnimGraphNodePropertyBinding;
|
|
class UK2Node_CustomEvent;
|
|
class IAnimBlueprintCompilationContext;
|
|
class IAnimBlueprintGeneratedClassCompiledData;
|
|
class IAnimBlueprintCompilerCreationContext;
|
|
class IAnimBlueprintCompilationBracketContext;
|
|
class IAnimBlueprintPostExpansionStepContext;
|
|
class IAnimBlueprintCopyTermDefaultsContext;
|
|
|
|
UCLASS(MinimalAPI)
|
|
class UAnimBlueprintExtension_Base : public UAnimBlueprintExtension
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
// Adds a map of struct eval handlers for the specified node
|
|
void AddStructEvalHandlers(UAnimGraphNode_Base* InNode, IAnimBlueprintCompilationContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData);
|
|
|
|
// Create an 'expanded' evaluation handler for the specified node, called in the compiler's node expansion step
|
|
void CreateEvaluationHandlerForNode(IAnimBlueprintCompilationContext& InCompilationContext, UAnimGraphNode_Base* InNode);
|
|
|
|
private:
|
|
// UAnimBlueprintExtension interface
|
|
virtual void HandleStartCompilingClass(const UClass* InClass, IAnimBlueprintCompilationBracketContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData) override;
|
|
virtual void HandleFinishCompilingClass(const UClass* InClass, IAnimBlueprintCompilationBracketContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData) override;
|
|
virtual void HandlePostExpansionStep(const UEdGraph* InGraph, IAnimBlueprintPostExpansionStepContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData) override;
|
|
virtual void HandleCopyTermDefaultsToDefaultObject(UObject* InDefaultObject, IAnimBlueprintCopyTermDefaultsContext& InCompilationContext, IAnimBlueprintExtensionCopyTermDefaultsContext& InPerExtensionContext) override;
|
|
|
|
// Patch all node's evaluation handlers
|
|
void PatchEvaluationHandlers(IAnimBlueprintCompilationBracketContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData);
|
|
|
|
private:
|
|
/** Record of a single copy operation */
|
|
struct FPropertyCopyRecord
|
|
{
|
|
FPropertyCopyRecord(UEdGraphPin* InDestPin, FProperty* InDestProperty, int32 InDestArrayIndex, TArray<FString>&& InDestPropertyPath)
|
|
: DestPin(InDestPin)
|
|
, DestProperty(InDestProperty)
|
|
, DestArrayIndex(InDestArrayIndex)
|
|
, DestPropertyPath(MoveTemp(InDestPropertyPath))
|
|
, LibraryCopyIndex(INDEX_NONE)
|
|
, LibraryBatchType(EPropertyAccessBatchType::Unbatched)
|
|
, Operation(EPostCopyOperation::None)
|
|
, bIsFastPath(true)
|
|
{}
|
|
|
|
FPropertyCopyRecord(const TArray<FString>& InSourcePropertyPath, const TArray<FString>& InDestPropertyPath)
|
|
: DestPin(nullptr)
|
|
, DestProperty(nullptr)
|
|
, DestArrayIndex(INDEX_NONE)
|
|
, SourcePropertyPath(InSourcePropertyPath)
|
|
, DestPropertyPath(InDestPropertyPath)
|
|
, LibraryCopyIndex(INDEX_NONE)
|
|
, LibraryBatchType(EPropertyAccessBatchType::Unbatched)
|
|
, Operation(EPostCopyOperation::None)
|
|
, bIsFastPath(true)
|
|
{}
|
|
|
|
bool IsFastPath() const
|
|
{
|
|
return SourcePropertyPath.Num() > 0 && bIsFastPath;
|
|
}
|
|
|
|
void InvalidateFastPath()
|
|
{
|
|
bIsFastPath = false;
|
|
}
|
|
|
|
/** The destination pin we are copying to */
|
|
UEdGraphPin* DestPin;
|
|
|
|
/** The destination property we are copying to (on an animation node) */
|
|
FProperty* DestProperty;
|
|
|
|
/** The array index we use if the destination property is an array */
|
|
int32 DestArrayIndex;
|
|
|
|
/** The property path relative to the class */
|
|
TArray<FString> SourcePropertyPath;
|
|
|
|
/** The property path relative to the class */
|
|
TArray<FString> DestPropertyPath;
|
|
|
|
/** The index of the copy in the property access library */
|
|
int32 LibraryCopyIndex;
|
|
|
|
/** the batch type within the property access library */
|
|
EPropertyAccessBatchType LibraryBatchType;
|
|
|
|
/** Any operation we want to perform post-copy on the destination data */
|
|
EPostCopyOperation Operation;
|
|
|
|
/** Fast-path flag */
|
|
bool bIsFastPath;
|
|
};
|
|
|
|
// Context used to build fast-path copy records
|
|
struct FCopyRecordGraphCheckContext
|
|
{
|
|
FCopyRecordGraphCheckContext(FPropertyCopyRecord& InCopyRecord, TArray<FPropertyCopyRecord>& InAdditionalCopyRecords, FCompilerResultsLog& InMessageLog)
|
|
: CopyRecord(&InCopyRecord)
|
|
, AdditionalCopyRecords(InAdditionalCopyRecords)
|
|
, MessageLog(InMessageLog)
|
|
{}
|
|
|
|
// Copy record we are operating on
|
|
FPropertyCopyRecord* CopyRecord;
|
|
|
|
// Things like split input pins can add additional copy records
|
|
TArray<FPropertyCopyRecord>& AdditionalCopyRecords;
|
|
|
|
// Message log used to recover original nodes
|
|
FCompilerResultsLog& MessageLog;
|
|
};
|
|
|
|
// Wireup record for a single anim node property (which might be an array)
|
|
struct FAnimNodeSinglePropertyHandler
|
|
{
|
|
/** Copy records */
|
|
TArray<FPropertyCopyRecord> CopyRecords;
|
|
|
|
// If the anim instance is the container target instead of the node.
|
|
bool bInstanceIsTarget;
|
|
|
|
FAnimNodeSinglePropertyHandler()
|
|
: bInstanceIsTarget(false)
|
|
{
|
|
}
|
|
};
|
|
|
|
/** BP execution handler for Anim node */
|
|
struct FEvaluationHandlerRecord
|
|
{
|
|
public:
|
|
// The Node this record came from
|
|
UAnimGraphNode_Base* AnimGraphNode;
|
|
|
|
// The node variable that the handler is in
|
|
FStructProperty* NodeVariableProperty;
|
|
|
|
// The specific evaluation handler inside the specified node
|
|
int32 EvaluationHandlerIdx;
|
|
|
|
// Whether or not our serviced properties are actually on the anim node
|
|
bool bServicesNodeProperties;
|
|
|
|
// Whether or not our serviced properties are actually on the instance instead of the node
|
|
bool bServicesInstanceProperties;
|
|
|
|
// Set of properties serviced by this handler (Map from property name to the record for that property)
|
|
TMap<FName, FAnimNodeSinglePropertyHandler> ServicedProperties;
|
|
|
|
// The generated custom event node
|
|
TArray<UEdGraphNode*> CustomEventNodes;
|
|
|
|
// The resulting function name
|
|
FName HandlerFunctionName;
|
|
|
|
public:
|
|
|
|
FEvaluationHandlerRecord()
|
|
: AnimGraphNode(nullptr)
|
|
, NodeVariableProperty(nullptr)
|
|
, EvaluationHandlerIdx(INDEX_NONE)
|
|
, bServicesNodeProperties(false)
|
|
, bServicesInstanceProperties(false)
|
|
, HandlerFunctionName(NAME_None)
|
|
{}
|
|
|
|
bool IsFastPath() const
|
|
{
|
|
for(TMap<FName, FAnimNodeSinglePropertyHandler>::TConstIterator It(ServicedProperties); It; ++It)
|
|
{
|
|
const FAnimNodeSinglePropertyHandler& AnimNodeSinglePropertyHandler = It.Value();
|
|
for (const FPropertyCopyRecord& CopyRecord : AnimNodeSinglePropertyHandler.CopyRecords)
|
|
{
|
|
if (!CopyRecord.IsFastPath())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IsValid() const
|
|
{
|
|
return NodeVariableProperty != nullptr;
|
|
}
|
|
|
|
void PatchFunctionNameAndCopyRecordsInto(FExposedValueHandler& Handler) const;
|
|
|
|
void RegisterPin(UEdGraphPin* DestPin, FProperty* AssociatedProperty, int32 AssociatedPropertyArrayIndex);
|
|
|
|
void RegisterPropertyBinding(FProperty* InProperty, const FAnimGraphNodePropertyBinding& InBinding);
|
|
|
|
FStructProperty* GetHandlerNodeProperty() const { return NodeVariableProperty; }
|
|
|
|
void BuildFastPathCopyRecords(IAnimBlueprintPostExpansionStepContext& InCompilationContext);
|
|
|
|
private:
|
|
|
|
bool CheckForVariableGet(FCopyRecordGraphCheckContext& Context, UEdGraphPin* DestPin);
|
|
|
|
bool CheckForLogicalNot(FCopyRecordGraphCheckContext& Context, UEdGraphPin* DestPin);
|
|
|
|
bool CheckForStructMemberAccess(FCopyRecordGraphCheckContext& Context, UEdGraphPin* DestPin);
|
|
|
|
bool CheckForMemberOnlyAccess(FPropertyCopyRecord& Context, UEdGraphPin* DestPin);
|
|
|
|
bool CheckForSplitPinAccess(FCopyRecordGraphCheckContext& Context, UEdGraphPin* DestPin);
|
|
|
|
bool CheckForArrayAccess(FCopyRecordGraphCheckContext& Context, UEdGraphPin* DestPin);
|
|
};
|
|
|
|
// Create an evaluation handler for the specified node/record
|
|
void CreateEvaluationHandler(IAnimBlueprintCompilationContext& InCompilationContext, UAnimGraphNode_Base* InNode, FEvaluationHandlerRecord& Record);
|
|
|
|
// Redirect any property accesses that are affected by constant folding
|
|
void RedirectPropertyAccesses(IAnimBlueprintCompilationContext& InCompilationContext, UAnimGraphNode_Base* InNode, FEvaluationHandlerRecord& InRecord);
|
|
|
|
private:
|
|
// Records of pose pins for later patchup with an associated evaluation handler
|
|
TMap<UAnimGraphNode_Base*, FEvaluationHandlerRecord> PerNodeStructEvalHandlers;
|
|
|
|
// List of successfully created evaluation handlers
|
|
TArray<FEvaluationHandlerRecord> ValidEvaluationHandlerList;
|
|
TMap<UAnimGraphNode_Base*, int32> ValidEvaluationHandlerMap;
|
|
|
|
// Set of used handler function names
|
|
TSet<FName> HandlerFunctionNames;
|
|
|
|
// Delegate handle for registering against library pre/post-compilation
|
|
FDelegateHandle PreLibraryCompiledDelegateHandle;
|
|
FDelegateHandle PostLibraryCompiledDelegateHandle;
|
|
|
|
// Base subsystem data containing eval handlers
|
|
UPROPERTY()
|
|
FAnimSubsystem_Base Subsystem;
|
|
}; |