// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "ControlRigBlueprint.h" #include "EdGraph/EdGraph.h" #include "Graph/ControlRigGraphNode.h" #include "Rigs/RigHierarchy.h" #include "Rigs/RigHierarchyController.h" #include "RigVMModel/RigVMGraph.h" #include "RigVMCore/RigVM.h" #include "EdGraph/RigVMEdGraph.h" #include "ControlRigGraph.generated.h" class UControlRigBlueprint; class UControlRigGraphSchema; class UControlRig; class URigVMController; struct FRigCurveContainer; UCLASS() class CONTROLRIGDEVELOPER_API UControlRigGraph : public URigVMEdGraph { GENERATED_BODY() public: UControlRigGraph(); /** Set up this graph */ virtual void InitializeFromBlueprint(URigVMBlueprint* InBlueprint) override; virtual bool HandleModifiedEvent_Internal(ERigVMGraphNotifType InNotifType, URigVMGraph* InGraph, UObject* InSubject) override; #if WITH_EDITOR const TArray>* GetBoneNameList(URigVMPin* InPin = nullptr) const { return GetElementNameList(ERigElementType::Bone); } const TArray>* GetControlNameList(URigVMPin* InPin = nullptr) const { return GetElementNameList(ERigElementType::Control); } const TArray>* GetControlNameListWithoutAnimationChannels(URigVMPin* InPin = nullptr) const { return &ControlNameListWithoutAnimationChannels; } const TArray>* GetNullNameList(URigVMPin* InPin = nullptr) const { return GetElementNameList(ERigElementType::Null); } const TArray>* GetCurveNameList(URigVMPin* InPin = nullptr) const { return GetElementNameList(ERigElementType::Curve); } const TArray>* GetConnectorNameList(URigVMPin* InPin = nullptr) const { return GetElementNameList(ERigElementType::Connector); } const TArray>* GetSocketNameList(URigVMPin* InPin = nullptr) const { return GetElementNameList(ERigElementType::Socket); } virtual const TArray>* GetNameListForWidget(const FString& InWidgetName) const override; void CacheNameLists(URigHierarchy* InHierarchy, const FRigVMDrawContainer* DrawContainer, TArray> ShapeLibraries); const TArray>* GetElementNameList(ERigElementType InElementType = ERigElementType::Bone) const; const TArray>* GetElementNameList(URigVMPin* InPin = nullptr) const; const TArray> GetSelectedElementsNameList() const; const TArray>* GetDrawingNameList(URigVMPin* InPin = nullptr) const; const TArray>* GetShapeNameList(URigVMPin* InPin = nullptr) const; FReply HandleGetSelectedClicked(URigVMEdGraph* InEdGraph, URigVMPin* InPin, FString InDefaultValue); FReply HandleBrowseClicked(URigVMEdGraph* InEdGraph, URigVMPin* InPin, FString InDefaultValue); private: template static bool IncludeElementInNameList(const T* InElement) { return true; } template void CacheNameListForHierarchy(UControlRig* InControlRig, URigHierarchy* InHierarchy, TArray>& OutNameList, bool bFilter = true) { TArray Names; for (auto Element : *InHierarchy) { if(Element->IsA()) { if(!bFilter || IncludeElementInNameList(Cast(Element))) { static const FLinearColor Color(FLinearColor(0.0, 112.f/255.f, 224.f/255.f)); FRigVMStringTag Tag; if(InControlRig) { if(const FRigElementKey* SourceKey = InControlRig->GetElementKeyRedirector().FindReverse(Element->GetKey())) { Tag = FRigVMStringTag(Element->GetKey().Name, Color); Names.Emplace(SourceKey->Name.ToString(), Tag); continue; } // look up the resolved name if(Element->GetType() == ERigElementType::Connector) { if(const FRigElementKeyRedirector::FCachedKeyArray* Cache = InControlRig->GetElementKeyRedirector().Find(Element->GetKey())) { if(!Cache->IsEmpty()) { Tag = FRigVMStringTag((*Cache)[0].GetKey().Name, Color); } } } } Names.Emplace(Element->GetName(), Tag); } } } Names.Sort(); OutNameList.Reset(); OutNameList.Add(MakeShared(FName(NAME_None).ToString())); for (const FRigVMStringWithTag& Name : Names) { OutNameList.Add(MakeShared(Name)); } } template void CacheNameList(const T& ElementList, TArray>& OutNameList) { TArray Names; for (auto Element : ElementList) { Names.Add(Element.Name.ToString()); } Names.Sort(); OutNameList.Reset(); OutNameList.Add(MakeShared(FName(NAME_None).ToString())); for (const FString& Name : Names) { OutNameList.Add(MakeShared(Name)); } } TMap>> ElementNameLists; TArray> ControlNameListWithoutAnimationChannels; TArray> DrawingNameList; TArray> ShapeNameList; int32 LastHierarchyTopologyVersion; static TArray> EmptyElementNameList; #endif friend class UControlRigGraphNode; friend class SRigVMGraphNode; friend class UControlRigBlueprint; }; template<> inline bool UControlRigGraph::IncludeElementInNameList(const FRigControlElement* InElement) { return !InElement->IsAnimationChannel(); }