void UAnimationGraphSchema::GetStateMachineMenuItems(FGraphContextMenuBuilder& ContextMenuBuilder) const
{
	// Show state machine helpers
	if ((ContextMenuBuilder.FromPin == NULL) || ((ContextMenuBuilder.FromPin->Direction == EGPD_Input) && (ContextMenuBuilder.FromPin->PinType.PinCategory == PC_Float)))
	{
		FString StateCategory(TEXT("State Machines"));

		// Create the additional entries to get state information
		TArray<UAnimStateNode*> States;
		UBlueprint* CurrentBlueprint = FBlueprintEditorUtils::FindBlueprintForGraphChecked(ContextMenuBuilder.CurrentGraph);
		FBlueprintEditorUtils::GetAllNodesOfClass(CurrentBlueprint, /*out*/ States);
	
		for (auto StateIt = States.CreateIterator(); StateIt; ++StateIt)
		{
			UAnimStateNode* StateNode = *StateIt;

			UK2Node_TransitionRuleGetter* NodeTemplate = ContextMenuBuilder.CreateTemplateNode<UK2Node_TransitionRuleGetter>();
			NodeTemplate->AssociatedStateNode = StateNode;
			NodeTemplate->GetterType = ETransitionGetter::ArbitraryState_GetBlendWeight;

			const FString OwnerName = StateNode->GetOuter()->GetName();
			const FString Title = FString::Printf(TEXT("Current %s for state '%s.%s'"), *UK2Node_TransitionRuleGetter::GetFriendlyName(NodeTemplate->GetterType), *OwnerName, *StateNode->GetStateName());

			TSharedPtr<FEdGraphSchemaAction_K2NewNode> Action = FK2ActionMenuBuilder::AddNewNodeAction(ContextMenuBuilder, StateCategory, Title, NodeTemplate->GetTooltip(), 0, NodeTemplate->GetKeywords());
			Action->NodeTemplate = NodeTemplate;
		}
	}
}
void UAnimationTransitionSchema::GetSourceStateActions(FGraphContextMenuBuilder& ContextMenuBuilder) const
{
	if ((ContextMenuBuilder.FromPin == NULL) || ((ContextMenuBuilder.FromPin->Direction == EGPD_Input) && (ContextMenuBuilder.FromPin->PinType.PinCategory == PC_Float)))
	{
		// Find the source state associated with this transition
		UAnimBlueprint* Blueprint = CastChecked<UAnimBlueprint>(FBlueprintEditorUtils::FindBlueprintForGraph(ContextMenuBuilder.CurrentGraph));

		if (UAnimBlueprintGeneratedClass* AnimBlueprintClass = Blueprint->GetAnimBlueprintSkeletonClass())
		{
			if (UAnimStateTransitionNode* TransNode = GetTransitionNodeFromGraph(AnimBlueprintClass->GetAnimBlueprintDebugData(), ContextMenuBuilder.CurrentGraph))
			{
				if (UAnimStateNode* SourceStateNode = Cast<UAnimStateNode>(TransNode->GetPreviousState()))
				{
					// Offer options from the source state

					// Sequence player positions
					ETransitionGetter::Type SequenceSpecificGetters[] =
					{
						ETransitionGetter::AnimationAsset_GetCurrentTime,
						ETransitionGetter::AnimationAsset_GetLength,
						ETransitionGetter::AnimationAsset_GetCurrentTimeFraction,
						ETransitionGetter::AnimationAsset_GetTimeFromEnd,
						ETransitionGetter::AnimationAsset_GetTimeFromEndFraction
					};

					TArray<UK2Node*> AssetPlayers;
					SourceStateNode->BoundGraph->GetNodesOfClassEx<UAnimGraphNode_Base, UK2Node>(/*out*/ AssetPlayers);

					const FString Category_AssetPlayer(TEXT("Asset Player"));

					for (int32 TypeIndex = 0; TypeIndex < ARRAY_COUNT(SequenceSpecificGetters); ++TypeIndex)
					{
						for (auto NodeIt = AssetPlayers.CreateConstIterator(); NodeIt; ++NodeIt)
						{
							UAnimGraphNode_Base* AnimNode = CastChecked<UAnimGraphNode_Base>(*NodeIt);
							
							if (AnimNode->DoesSupportTimeForTransitionGetter())
							{
								UK2Node_TransitionRuleGetter* NodeTemplate = ContextMenuBuilder.CreateTemplateNode<UK2Node_TransitionRuleGetter>();

								FString AssetName;

								UAnimationAsset * AnimAsset = AnimNode->GetAnimationAsset();
								if (AnimAsset)
								{
									NodeTemplate->AssociatedAnimAssetPlayerNode = AnimNode;
									AssetName = AnimAsset->GetName();
								}

								NodeTemplate->GetterType = SequenceSpecificGetters[TypeIndex];

								FFormatNamedArguments Args;
								Args.Add(TEXT("NodeName"), UK2Node_TransitionRuleGetter::GetFriendlyName(NodeTemplate->GetterType));
								Args.Add(TEXT("AssetName"), FText::FromString(AssetName));
								FText Title = FText::Format(LOCTEXT("TransitionFor", "{NodeName} for '{AssetName}'"), Args);

								TSharedPtr<FEdGraphSchemaAction_K2NewNode> Action = FK2ActionMenuBuilder::AddNewNodeAction(ContextMenuBuilder, Category_AssetPlayer, Title, NodeTemplate->GetTooltipText().ToString(), 0, NodeTemplate->GetKeywords());
								Action->NodeTemplate = NodeTemplate;
							}
						}
					}

					// Non-sequence specific ones
					ETransitionGetter::Type NonSpecificGetters[] =
					{
						ETransitionGetter::CurrentTransitionDuration,
						ETransitionGetter::CurrentState_ElapsedTime,
						ETransitionGetter::CurrentState_GetBlendWeight
					};

					for (int32 TypeIndex = 0; TypeIndex < ARRAY_COUNT(NonSpecificGetters); ++TypeIndex)
					{
						FString Category_Transition(TEXT("Transition"));

						UK2Node_TransitionRuleGetter* NodeTemplate = ContextMenuBuilder.CreateTemplateNode<UK2Node_TransitionRuleGetter>();
						NodeTemplate->GetterType = NonSpecificGetters[TypeIndex];

						FText Title = UK2Node_TransitionRuleGetter::GetFriendlyName(NodeTemplate->GetterType);

						TSharedPtr<FEdGraphSchemaAction_K2NewNode> Action = FK2ActionMenuBuilder::AddNewNodeAction(ContextMenuBuilder, Category_Transition, Title, NodeTemplate->GetTooltipText().ToString(), 0, NodeTemplate->GetKeywords());
						Action->NodeTemplate = NodeTemplate;
					}
				}
			}
		}
	}
}