// Copyright Epic Games, Inc. All Rights Reserved. #include "AnimGraphNode_AssetPlayerBase.h" #include "EdGraphSchema_K2.h" #include "Animation/AnimComposite.h" #include "Animation/BlendSpaceBase.h" #include "Animation/AimOffsetBlendSpace.h" #include "Animation/AimOffsetBlendSpace1D.h" #include "AnimGraphNode_SequencePlayer.h" #include "AnimGraphNode_SequenceEvaluator.h" #include "AnimGraphNode_RotationOffsetBlendSpace.h" #include "AnimGraphNode_BlendSpacePlayer.h" #include "AnimGraphNode_BlendSpaceEvaluator.h" #include "Animation/PoseAsset.h" #include "AnimGraphNode_PoseBlendNode.h" #include "AnimGraphNode_PoseByName.h" #include "AnimGraphNode_PoseDriver.h" #include "UObject/UObjectIterator.h" #include "Animation/AnimLayerInterface.h" #include "IAnimBlueprintCompilerHandlerCollection.h" #include "AnimBlueprintCompilerHandler_Base.h" #include "IAnimBlueprintGeneratedClassCompiledData.h" #include "IAnimBlueprintCompilationContext.h" void UAnimGraphNode_AssetPlayerBase::PinConnectionListChanged(UEdGraphPin* Pin) { Super::PinConnectionListChanged(Pin); if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Object) { // recache visualization now an asset pin's connection is changed if (const UEdGraphSchema* Schema = GetSchema()) { Schema->ForceVisualizationCacheClear(); } } } void UAnimGraphNode_AssetPlayerBase::PinDefaultValueChanged(UEdGraphPin* Pin) { Super::PinDefaultValueChanged(Pin); if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Object) { // recache visualization now an asset pin's default value has changed if (const UEdGraphSchema* Schema = GetSchema()) { Schema->ForceVisualizationCacheClear(); } } } void UAnimGraphNode_AssetPlayerBase::OnProcessDuringCompilation(IAnimBlueprintCompilationContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData) { UBlueprint* Blueprint = GetBlueprint(); // Process Asset Player nodes to, if necessary cache off their node index for retrieval at runtime (used for evaluating Automatic Rule Transitions when using Layer nodes) auto ProcessGraph = [this, &OutCompiledData](UEdGraph* Graph) { // Make sure we do not process the default AnimGraph static const FName DefaultAnimGraphName("AnimGraph"); if (Graph->GetFName() != DefaultAnimGraphName) { FString GraphName = Graph->GetName(); // Also make sure we do not process any empty stub graphs if (!GraphName.Contains(ANIM_FUNC_DECORATOR)) { if (Graph->Nodes.ContainsByPredicate([this, &OutCompiledData](UEdGraphNode* Node) { return Node->NodeGuid == NodeGuid; })) { if (int32* IndexPtr = OutCompiledData.GetAnimBlueprintDebugData().NodeGuidToIndexMap.Find(NodeGuid)) { FGraphAssetPlayerInformation& Info = OutCompiledData.GetGraphAssetPlayerInformation().FindOrAdd(FName(*GraphName)); Info.PlayerNodeIndices.AddUnique(*IndexPtr); } } } } }; // Check for any definition of a layer graph for (UEdGraph* Graph : Blueprint->FunctionGraphs) { ProcessGraph(Graph); } // Check for any implemented AnimLayer interface graphs for (FBPInterfaceDescription& InterfaceDesc : Blueprint->ImplementedInterfaces) { // Only process Anim Layer interfaces if (InterfaceDesc.Interface->IsChildOf()) { for (UEdGraph* Graph : InterfaceDesc.Graphs) { ProcessGraph(Graph); } } } } UClass* GetNodeClassForAsset(const UClass* AssetClass) { UClass* NodeClass = nullptr; // Iterate over all classes.. for (TObjectIterator ClassIt; ClassIt; ++ClassIt) { UClass *Class = *ClassIt; // Look for AnimGraphNode classes if (Class->IsChildOf(UAnimGraphNode_Base::StaticClass())) { // See if this node is the 'primary handler' for this asset type const UAnimGraphNode_Base* NodeCDO = Class->GetDefaultObject(); if (NodeCDO->SupportsAssetClass(AssetClass) == EAnimAssetHandlerType::PrimaryHandler) { NodeClass = Class; break; } } } return NodeClass; } bool SupportNodeClassForAsset(const UClass* AssetClass, UClass* NodeClass) { // Get node CDO const UAnimGraphNode_Base* NodeCDO = NodeClass->GetDefaultObject(); // See if this node supports this asset type (primary or not) return (NodeCDO->SupportsAssetClass(AssetClass) != EAnimAssetHandlerType::NotSupported); }