You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2821607 on 2016/01/08 by Mieszko.Zielinski Added a way to limit amount of information logged by vlog by discarding logs from classes from outside of class whitelist #UE4 This feature was followed by refactoring of functions taking FVisualLogEntry pointers to use references instead. #rb Lukasz.Furman #codereview John.Abercrombie Change 2828384 on 2016/01/14 by Mieszko.Zielinski Back out of visual log refactor done as part of CL#2821607 #UE4 Change 2855722 on 2016/02/04 by Zak.Middleton #ue4 - Expose PrimitiveComponent GetCollisionEnabled(), IsCollisionEnabled(), IsQueryCollisionEnabled(), IsPhysicsCollisionEnabled() functions to blueprints. #rb Daniel.Broder, Ori.Cohen #codereview Bob.Tellez #jira UE-26411 Change 2855737 on 2016/02/04 by James.Golding Add test AssetUserData C++ class to QAGame Change 2855739 on 2016/02/04 by James.Golding PR #1858 : Add abstract and editinlinenew to AssetUserData class, so derived classes can be added to assets via details panel https://github.com/EpicGames/UnrealEngine/pull/1858 #github 1858 #jira UE-24494 #rb thomas.sarkanen Change 2855842 on 2016/02/04 by James.Golding UE-23968 : Add clamping to Friction, Restitution, Density and RaiseMassToPower properties of PhysicalMaterial #codereview ori.cohen #rb thomas.sarkanen Change 2855843 on 2016/02/04 by James.Golding PR #1984 : Add 'AssetUserData' support to AnimationAsset/Texture https://github.com/EpicGames/UnrealEngine/pull/1984 #github 1984 #jira UE-25913 #rb thomas.sarkanen Change 2855844 on 2016/02/04 by James.Golding UE-23176 Fix incorrect clamping in GenerateKDopAsSimpleCollision() which could cause degenerate hulls Also don't 'nudge' kdops if there are other primitives present, will offset from mesh we were fitting around #rb thomas.sarkanen Change 2855850 on 2016/02/04 by Benn.Gallagher Update required LOD bones when associating a cloth chunk that uses bones that aren't weighted to that LOD #rb Martin.Wilson Change 2856409 on 2016/02/04 by Zak.Middleton #ue4 - Change LogSpawn warnings to normal logs for cases that are common and valid during gameplay (failed due to collision at the target location, or failed because it is destroyed in the process of spawning, ie projectile spawned in a target). #codereview Jeff.Farris Change 2857018 on 2016/02/05 by Benn.Gallagher Fixes for various anim graph related subgraph issues/crashes #rb Ben.Cosh Change 2857193 on 2016/02/05 by Lukasz.Furman extended crowd agent interface to handle avoidance groups #ue4 UE-24823 #1896 Change 2857200 on 2016/02/05 by Lukasz.Furman fixed memory leak in CrowdManager #ue UE-26516 #2026 #codereview Mieszko.Zielinski Change 2857417 on 2016/02/05 by Lina.Halper Add keyword for animation functions Change 2858854 on 2016/02/08 by Benn.Gallagher Fixed pose evaluator customizations being processed at the wrong time which caused properties to always be re-added even if removed from the details panel, causing duplicated entries. #jira UE-8421 #rb Lina.Halper Change 2858855 on 2016/02/08 by Benn.Gallagher Fixed blendspace players only reporting normalized time when using a time getter in an anim graph transition. #rb Lina.Halper Change 2859159 on 2016/02/08 by Aaron.McLeran UE-25586 Fix for reporting audio memory usage - Realtime decompressed sounds that have CachedRealtimeFirstBuffers need to report the compressed asset size Change 2859192 on 2016/02/08 by Laurent.Delayen Removed check disallowing cooked additive animations from using AnimationRelative and AnimationScale retargeting modes (on the root bone or editor). Skip AnimationRelative retargeting for baked additive animations since it gets cancelled out during the additive creation process. #rb martin.wilson #codereview lina.halper Change 2859238 on 2016/02/08 by Lina.Halper Git pull request #1895 Change 2859239 on 2016/02/08 by Lina.Halper Git pull request #1813 Change 2859453 on 2016/02/08 by Aaron.McLeran [CL 2868856 by Marc Audy in Main branch]
470 lines
16 KiB
C++
470 lines
16 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
AnimationGraphSchema.cpp
|
|
=============================================================================*/
|
|
|
|
#include "AnimGraphPrivatePCH.h"
|
|
#include "BlueprintUtilities.h"
|
|
#include "GraphEditorActions.h"
|
|
#include "ScopedTransaction.h"
|
|
#include "AssetData.h"
|
|
#include "AnimationGraphSchema.h"
|
|
#include "K2Node_TransitionRuleGetter.h"
|
|
#include "AnimStateNode.h"
|
|
#include "AnimGraphNode_BlendSpacePlayer.h"
|
|
#include "AnimGraphNode_ComponentToLocalSpace.h"
|
|
#include "AnimGraphNode_LocalToComponentSpace.h"
|
|
#include "AnimGraphNode_Root.h"
|
|
#include "AnimGraphNode_RotationOffsetBlendSpace.h"
|
|
#include "AnimGraphNode_SequencePlayer.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "AnimationGraphSchema"
|
|
|
|
/////////////////////////////////////////////////////
|
|
// UAnimationGraphSchema
|
|
|
|
UAnimationGraphSchema::UAnimationGraphSchema(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
PN_SequenceName = TEXT("Sequence");
|
|
|
|
NAME_NeverAsPin = TEXT("NeverAsPin");
|
|
NAME_PinHiddenByDefault = TEXT("PinHiddenByDefault");
|
|
NAME_PinShownByDefault = TEXT("PinShownByDefault");
|
|
NAME_AlwaysAsPin = TEXT("AlwaysAsPin");
|
|
NAME_OnEvaluate = TEXT("OnEvaluate");
|
|
NAME_CustomizeProperty = TEXT("CustomizeProperty");
|
|
DefaultEvaluationHandlerName = TEXT("EvaluateGraphExposedInputs");
|
|
}
|
|
|
|
FLinearColor UAnimationGraphSchema::GetPinTypeColor(const FEdGraphPinType& PinType) const
|
|
{
|
|
const bool bAdditive = PinType.PinSubCategory == TEXT("Additive");
|
|
if (UAnimationGraphSchema::IsLocalSpacePosePin(PinType))
|
|
{
|
|
if (bAdditive)
|
|
{
|
|
return FLinearColor(0.12, 0.60, 0.10);
|
|
}
|
|
else
|
|
{
|
|
return FLinearColor::White;
|
|
}
|
|
}
|
|
else if (UAnimationGraphSchema::IsComponentSpacePosePin(PinType))
|
|
{
|
|
//@TODO: Pick better colors
|
|
if (bAdditive)
|
|
{
|
|
return FLinearColor(0.12, 0.60, 0.60);
|
|
}
|
|
else
|
|
{
|
|
return FLinearColor(0.20f, 0.50f, 1.00f);
|
|
}
|
|
}
|
|
|
|
return Super::GetPinTypeColor(PinType);
|
|
}
|
|
|
|
EGraphType UAnimationGraphSchema::GetGraphType(const UEdGraph* TestEdGraph) const
|
|
{
|
|
return GT_Animation;
|
|
}
|
|
|
|
void UAnimationGraphSchema::CreateDefaultNodesForGraph(UEdGraph& Graph) const
|
|
{
|
|
// Create the result node
|
|
FGraphNodeCreator<UAnimGraphNode_Root> NodeCreator(Graph);
|
|
UAnimGraphNode_Root* ResultSinkNode = NodeCreator.CreateNode();
|
|
NodeCreator.Finalize();
|
|
SetNodeMetaData(ResultSinkNode, FNodeMetadata::DefaultGraphNode);
|
|
}
|
|
|
|
void UAnimationGraphSchema::HandleGraphBeingDeleted(UEdGraph& GraphBeingRemoved) const
|
|
{
|
|
if (UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(&GraphBeingRemoved))
|
|
{
|
|
// Look for state nodes that reference this graph
|
|
TArray<UAnimStateNodeBase*> StateNodes;
|
|
FBlueprintEditorUtils::GetAllNodesOfClassEx<UAnimStateNode>(Blueprint, StateNodes);
|
|
|
|
TSet<UAnimStateNodeBase*> NodesToDelete;
|
|
for (int32 i = 0; i < StateNodes.Num(); ++i)
|
|
{
|
|
UAnimStateNodeBase* StateNode = StateNodes[i];
|
|
if (StateNode->GetBoundGraph() == &GraphBeingRemoved)
|
|
{
|
|
NodesToDelete.Add(StateNode);
|
|
}
|
|
}
|
|
|
|
// Delete the node that owns us
|
|
ensure(NodesToDelete.Num() <= 1);
|
|
for (TSet<UAnimStateNodeBase*>::TIterator It(NodesToDelete); It; ++It)
|
|
{
|
|
UAnimStateNodeBase* NodeToDelete = *It;
|
|
|
|
FBlueprintEditorUtils::RemoveNode(Blueprint, NodeToDelete, true);
|
|
|
|
// Prevent re-entrancy here
|
|
NodeToDelete->ClearBoundGraph();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool UAnimationGraphSchema::IsPosePin(const FEdGraphPinType& PinType)
|
|
{
|
|
return IsLocalSpacePosePin(PinType) || IsComponentSpacePosePin(PinType);
|
|
}
|
|
|
|
bool UAnimationGraphSchema::IsLocalSpacePosePin(const FEdGraphPinType& PinType)
|
|
{
|
|
const UAnimationGraphSchema* Schema = GetDefault<UAnimationGraphSchema>();
|
|
|
|
UScriptStruct* PoseLinkStruct = FPoseLink::StaticStruct();
|
|
return (PinType.PinCategory == Schema->PC_Struct) && (PinType.PinSubCategoryObject == PoseLinkStruct);
|
|
}
|
|
|
|
bool UAnimationGraphSchema::IsComponentSpacePosePin(const FEdGraphPinType& PinType)
|
|
{
|
|
const UAnimationGraphSchema* Schema = GetDefault<UAnimationGraphSchema>();
|
|
|
|
UScriptStruct* ComponentSpacePoseLinkStruct = FComponentSpacePoseLink::StaticStruct();
|
|
return (PinType.PinCategory == Schema->PC_Struct) && (PinType.PinSubCategoryObject == ComponentSpacePoseLinkStruct);
|
|
}
|
|
|
|
const FPinConnectionResponse UAnimationGraphSchema::DetermineConnectionResponseOfCompatibleTypedPins(const UEdGraphPin* PinA, const UEdGraphPin* PinB, const UEdGraphPin* InputPin, const UEdGraphPin* OutputPin) const
|
|
{
|
|
// Enforce a tree hierarchy; where poses can only have one output (parent) connection
|
|
if (IsPosePin(OutputPin->PinType) && IsPosePin(InputPin->PinType))
|
|
{
|
|
if ((OutputPin->LinkedTo.Num() > 0) || (InputPin->LinkedTo.Num() > 0))
|
|
{
|
|
const ECanCreateConnectionResponse ReplyBreakOutputs = CONNECT_RESPONSE_BREAK_OTHERS_AB;
|
|
return FPinConnectionResponse(ReplyBreakOutputs, TEXT("Replace existing connections"));
|
|
}
|
|
}
|
|
|
|
// Fall back to standard K2 rules
|
|
return Super::DetermineConnectionResponseOfCompatibleTypedPins(PinA, PinB, InputPin, OutputPin);
|
|
}
|
|
|
|
bool UAnimationGraphSchema::ArePinsCompatible(const UEdGraphPin* PinA, const UEdGraphPin* PinB, const UClass* CallingContext, bool bIgnoreArray) const
|
|
{
|
|
// both are pose pin, but doesn't match type, then return false;
|
|
if (IsPosePin(PinA->PinType) && IsPosePin(PinB->PinType) && IsLocalSpacePosePin(PinA->PinType) != IsLocalSpacePosePin(PinB->PinType))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return Super::ArePinsCompatible(PinA, PinB, CallingContext, bIgnoreArray);
|
|
}
|
|
|
|
bool UAnimationGraphSchema::DoesSupportAnimNotifyActions() const
|
|
{
|
|
// Don't offer notify items in anim graph
|
|
return false;
|
|
}
|
|
|
|
bool UAnimationGraphSchema::SearchForAutocastFunction(const UEdGraphPin* OutputPin, const UEdGraphPin* InputPin, FName& TargetFunction, /*out*/ UClass*& FunctionOwner) const
|
|
{
|
|
if (IsComponentSpacePosePin(OutputPin->PinType) && IsLocalSpacePosePin(InputPin->PinType))
|
|
{
|
|
// Insert a Component To LocalSpace conversion
|
|
return true;
|
|
}
|
|
else if (IsLocalSpacePosePin(OutputPin->PinType) && IsComponentSpacePosePin(InputPin->PinType))
|
|
{
|
|
// Insert a Local To ComponentSpace conversion
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return Super::SearchForAutocastFunction(OutputPin, InputPin, TargetFunction, FunctionOwner);
|
|
}
|
|
}
|
|
|
|
bool UAnimationGraphSchema::CreateAutomaticConversionNodeAndConnections(UEdGraphPin* PinA, UEdGraphPin* PinB) const
|
|
{
|
|
// Determine which pin is an input and which pin is an output
|
|
UEdGraphPin* InputPin = NULL;
|
|
UEdGraphPin* OutputPin = NULL;
|
|
if (!CategorizePinsByDirection(PinA, PinB, /*out*/ InputPin, /*out*/ OutputPin))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Look for animation specific conversion operations
|
|
UK2Node* TemplateNode = NULL;
|
|
if (IsComponentSpacePosePin(OutputPin->PinType) && IsLocalSpacePosePin(InputPin->PinType))
|
|
{
|
|
TemplateNode = NewObject<UAnimGraphNode_ComponentToLocalSpace>();
|
|
}
|
|
else if (IsLocalSpacePosePin(OutputPin->PinType) && IsComponentSpacePosePin(InputPin->PinType))
|
|
{
|
|
TemplateNode = NewObject<UAnimGraphNode_LocalToComponentSpace>();
|
|
}
|
|
|
|
// Spawn the conversion node if it's specific to animation
|
|
if (TemplateNode != NULL)
|
|
{
|
|
UEdGraph* Graph = InputPin->GetOwningNode()->GetGraph();
|
|
FVector2D AverageLocation = CalculateAveragePositionBetweenNodes(InputPin, OutputPin);
|
|
|
|
UK2Node* ConversionNode = FEdGraphSchemaAction_K2NewNode::SpawnNodeFromTemplate<UK2Node>(Graph, TemplateNode, AverageLocation);
|
|
AutowireConversionNode(InputPin, OutputPin, ConversionNode);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Give the regular conversions a shot
|
|
return Super::CreateAutomaticConversionNodeAndConnections(PinA, PinB);
|
|
}
|
|
}
|
|
|
|
bool IsAimOffsetBlendSpace(UBlendSpaceBase* BlendSpace)
|
|
{
|
|
return BlendSpace->IsA(UAimOffsetBlendSpace::StaticClass()) ||
|
|
BlendSpace->IsA(UAimOffsetBlendSpace1D::StaticClass());
|
|
}
|
|
|
|
void UAnimationGraphSchema::SpawnNodeFromAsset(UAnimationAsset* Asset, const FVector2D& GraphPosition, UEdGraph* Graph, UEdGraphPin* PinIfAvailable)
|
|
{
|
|
check(Graph);
|
|
check(Graph->GetSchema()->IsA(UAnimationGraphSchema::StaticClass()));
|
|
check(Asset);
|
|
|
|
UAnimBlueprint* AnimBlueprint = Cast<UAnimBlueprint>(FBlueprintEditorUtils::FindBlueprintForGraph(Graph));
|
|
|
|
const bool bSkelMatch = (AnimBlueprint != NULL) && (AnimBlueprint->TargetSkeleton == Asset->GetSkeleton());
|
|
const bool bTypeMatch = (PinIfAvailable == NULL) || UAnimationGraphSchema::IsLocalSpacePosePin(PinIfAvailable->PinType);
|
|
const bool bDirectionMatch = (PinIfAvailable == NULL) || (PinIfAvailable->Direction == EGPD_Input);
|
|
|
|
if (bSkelMatch && bTypeMatch && bDirectionMatch)
|
|
{
|
|
FEdGraphSchemaAction_K2NewNode Action;
|
|
|
|
if (UAnimSequence* Sequence = Cast<UAnimSequence>(Asset))
|
|
{
|
|
UAnimGraphNode_SequencePlayer* PlayerNode = NewObject<UAnimGraphNode_SequencePlayer>();
|
|
PlayerNode->Node.Sequence = Sequence;
|
|
Action.NodeTemplate = PlayerNode;
|
|
}
|
|
else if (UBlendSpaceBase* BlendSpace = Cast<UBlendSpaceBase>(Asset))
|
|
{
|
|
if (IsAimOffsetBlendSpace(BlendSpace))
|
|
{
|
|
UAnimGraphNode_RotationOffsetBlendSpace* PlayerNode = NewObject<UAnimGraphNode_RotationOffsetBlendSpace>();
|
|
PlayerNode->Node.BlendSpace = BlendSpace;
|
|
|
|
Action.NodeTemplate = PlayerNode;
|
|
}
|
|
else
|
|
{
|
|
UAnimGraphNode_BlendSpacePlayer* PlayerNode = NewObject<UAnimGraphNode_BlendSpacePlayer>();
|
|
PlayerNode->Node.BlendSpace = BlendSpace;
|
|
|
|
Action.NodeTemplate = PlayerNode;
|
|
}
|
|
}
|
|
else if (UAnimComposite* Composite = Cast<UAnimComposite>(Asset))
|
|
{
|
|
UAnimGraphNode_SequencePlayer* PlayerNode = NewObject<UAnimGraphNode_SequencePlayer>();
|
|
PlayerNode->Node.Sequence = Composite;
|
|
Action.NodeTemplate = PlayerNode;
|
|
}
|
|
else
|
|
{
|
|
//unknown type
|
|
return;
|
|
}
|
|
|
|
Action.PerformAction(Graph, PinIfAvailable, GraphPosition);
|
|
}
|
|
}
|
|
|
|
|
|
void UAnimationGraphSchema::UpdateNodeWithAsset(UK2Node* K2Node, UAnimationAsset* Asset)
|
|
{
|
|
if (Asset != NULL)
|
|
{
|
|
if (UAnimGraphNode_SequencePlayer* SequencePlayerNode = Cast<UAnimGraphNode_SequencePlayer>(K2Node))
|
|
{
|
|
if (UAnimSequence* Sequence = Cast<UAnimSequence>(Asset))
|
|
{
|
|
// Skeleton matches, and it's a sequence player; replace the existing sequence with the dragged one
|
|
SequencePlayerNode->Node.Sequence = Sequence;
|
|
}
|
|
}
|
|
else if (UBlendSpace* BlendSpace = Cast<UBlendSpace>(Asset))
|
|
{
|
|
if (IsAimOffsetBlendSpace(BlendSpace))
|
|
{
|
|
if (UAnimGraphNode_RotationOffsetBlendSpace* RotationOffsetNode = Cast<UAnimGraphNode_RotationOffsetBlendSpace>(K2Node))
|
|
{
|
|
// Skeleton matches, and it's a blendspace player; replace the existing blendspace with the dragged one
|
|
RotationOffsetNode->Node.BlendSpace = BlendSpace;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (UAnimGraphNode_BlendSpacePlayer* BlendSpacePlayerNode = Cast<UAnimGraphNode_BlendSpacePlayer>(K2Node))
|
|
{
|
|
// Skeleton matches, and it's a blendspace player; replace the existing blendspace with the dragged one
|
|
BlendSpacePlayerNode->Node.BlendSpace = BlendSpace;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void UAnimationGraphSchema::DroppedAssetsOnGraph( const TArray<FAssetData>& Assets, const FVector2D& GraphPosition, UEdGraph* Graph ) const
|
|
{
|
|
UAnimationAsset* Asset = FAssetData::GetFirstAsset<UAnimationAsset>(Assets);
|
|
if ((Asset != NULL) && (Graph != NULL))
|
|
{
|
|
SpawnNodeFromAsset(Asset, GraphPosition, Graph, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void UAnimationGraphSchema::DroppedAssetsOnNode(const TArray<FAssetData>& Assets, const FVector2D& GraphPosition, UEdGraphNode* Node) const
|
|
{
|
|
UAnimationAsset* Asset = FAssetData::GetFirstAsset<UAnimationAsset>(Assets);
|
|
UK2Node* K2Node = Cast<UK2Node>(Node);
|
|
if ((Asset != NULL) && (K2Node!= NULL))
|
|
{
|
|
UpdateNodeWithAsset(K2Node, Asset);
|
|
}
|
|
}
|
|
|
|
void UAnimationGraphSchema::DroppedAssetsOnPin(const TArray<FAssetData>& Assets, const FVector2D& GraphPosition, UEdGraphPin* Pin) const
|
|
{
|
|
UAnimationAsset* Asset = FAssetData::GetFirstAsset<UAnimationAsset>(Assets);
|
|
if ((Asset != NULL) && (Pin != NULL))
|
|
{
|
|
SpawnNodeFromAsset(Asset, GraphPosition, Pin->GetOwningNode()->GetGraph(), Pin);
|
|
}
|
|
}
|
|
|
|
void UAnimationGraphSchema::GetAssetsNodeHoverMessage(const TArray<FAssetData>& Assets, const UEdGraphNode* HoverNode, FString& OutTooltipText, bool& OutOkIcon) const
|
|
{
|
|
UAnimationAsset* Asset = FAssetData::GetFirstAsset<UAnimationAsset>(Assets);
|
|
if ((Asset == NULL) || (HoverNode == NULL))
|
|
{
|
|
OutTooltipText = TEXT("");
|
|
OutOkIcon = false;
|
|
return;
|
|
}
|
|
|
|
const UK2Node* PlayerNodeUnderCursor = NULL;
|
|
if (Asset->IsA(UAnimSequence::StaticClass()))
|
|
{
|
|
PlayerNodeUnderCursor = Cast<const UAnimGraphNode_SequencePlayer>(HoverNode);
|
|
}
|
|
else if (Asset->IsA(UBlendSpace::StaticClass()))
|
|
{
|
|
UBlendSpace* BlendSpace = CastChecked<UBlendSpace>(Asset);
|
|
if (IsAimOffsetBlendSpace(BlendSpace))
|
|
{
|
|
PlayerNodeUnderCursor = Cast<const UAnimGraphNode_RotationOffsetBlendSpace>(HoverNode);
|
|
}
|
|
else
|
|
{
|
|
PlayerNodeUnderCursor = Cast<const UAnimGraphNode_BlendSpacePlayer>(HoverNode);
|
|
}
|
|
}
|
|
|
|
// this one only should happen when there is an Anim Blueprint
|
|
UAnimBlueprint* AnimBlueprint = Cast<UAnimBlueprint>(FBlueprintEditorUtils::FindBlueprintForNode(HoverNode));
|
|
const bool bSkelMatch = (AnimBlueprint != NULL) && (AnimBlueprint->TargetSkeleton == Asset->GetSkeleton());
|
|
|
|
if (!bSkelMatch)
|
|
{
|
|
OutOkIcon = false;
|
|
OutTooltipText = FString::Printf(TEXT("Skeletons are not compatible"));
|
|
}
|
|
else if (PlayerNodeUnderCursor != NULL)
|
|
{
|
|
OutOkIcon = true;
|
|
OutTooltipText = FString::Printf(TEXT("Change node to play %s"), *(Asset->GetName()));
|
|
}
|
|
else
|
|
{
|
|
OutOkIcon = false;
|
|
OutTooltipText = FString::Printf(TEXT("Cannot replace '%s' with a sequence player"), *(HoverNode->GetName()));
|
|
}
|
|
}
|
|
|
|
void UAnimationGraphSchema::GetAssetsPinHoverMessage(const TArray<FAssetData>& Assets, const UEdGraphPin* HoverPin, FString& OutTooltipText, bool& OutOkIcon) const
|
|
{
|
|
UAnimationAsset* Asset = FAssetData::GetFirstAsset<UAnimationAsset>(Assets);
|
|
if ((Asset == NULL) || (HoverPin == NULL))
|
|
{
|
|
OutTooltipText = TEXT("");
|
|
OutOkIcon = false;
|
|
return;
|
|
}
|
|
|
|
// this one only should happen when there is an Anim Blueprint
|
|
UAnimBlueprint* AnimBlueprint = Cast<UAnimBlueprint>(FBlueprintEditorUtils::FindBlueprintForNode(HoverPin->GetOwningNode()));
|
|
|
|
const bool bSkelMatch = (AnimBlueprint != NULL) && (AnimBlueprint->TargetSkeleton == Asset->GetSkeleton());
|
|
const bool bTypeMatch = UAnimationGraphSchema::IsLocalSpacePosePin(HoverPin->PinType);
|
|
const bool bDirectionMatch = HoverPin->Direction == EGPD_Input;
|
|
|
|
if (bSkelMatch && bTypeMatch && bDirectionMatch)
|
|
{
|
|
OutOkIcon = true;
|
|
OutTooltipText = FString::Printf(TEXT("Play %s and feed to %s"), *(Asset->GetName()), *HoverPin->PinName);
|
|
}
|
|
else
|
|
{
|
|
OutOkIcon = false;
|
|
OutTooltipText = FString::Printf(TEXT("Type or direction mismatch; must be wired to a pose input"));
|
|
}
|
|
}
|
|
|
|
void UAnimationGraphSchema::GetAssetsGraphHoverMessage(const TArray<FAssetData>& Assets, const UEdGraph* HoverGraph, FString& OutTooltipText, bool& OutOkIcon) const
|
|
{
|
|
UAnimationAsset* Asset = FAssetData::GetFirstAsset<UAnimationAsset>(Assets);
|
|
if (Asset)
|
|
{
|
|
UAnimBlueprint* AnimBlueprint = Cast<UAnimBlueprint>(FBlueprintEditorUtils::FindBlueprintForGraph(HoverGraph));
|
|
const bool bSkelMatch = (AnimBlueprint != NULL) && (AnimBlueprint->TargetSkeleton == Asset->GetSkeleton());
|
|
if (!bSkelMatch)
|
|
{
|
|
OutOkIcon = false;
|
|
OutTooltipText = FString::Printf(TEXT("Skeletons are not compatible"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void UAnimationGraphSchema::GetContextMenuActions(const UEdGraph* CurrentGraph, const UEdGraphNode* InGraphNode, const UEdGraphPin* InGraphPin, FMenuBuilder* MenuBuilder, bool bIsDebugging) const
|
|
{
|
|
Super::GetContextMenuActions(CurrentGraph, InGraphNode, InGraphPin, MenuBuilder, bIsDebugging);
|
|
}
|
|
|
|
FText UAnimationGraphSchema::GetPinDisplayName(const UEdGraphPin* Pin) const
|
|
{
|
|
check(Pin != NULL);
|
|
|
|
FText DisplayName = Super::GetPinDisplayName(Pin);
|
|
|
|
if (UAnimGraphNode_Base* Node = Cast<UAnimGraphNode_Base>(Pin->GetOwningNode()))
|
|
{
|
|
FString ProcessedDisplayName = DisplayName.ToString();
|
|
Node->PostProcessPinName(Pin, ProcessedDisplayName);
|
|
DisplayName = FText::FromString(ProcessedDisplayName);
|
|
}
|
|
|
|
return DisplayName;
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|