Files
UnrealEngineUWP/Engine/Source/Editor/BlueprintGraph/Private/K2Node_InputAxisEvent.cpp
Michael Schoell 75200e5a0d Cached node titles can now be forced to refresh without iteration over every node.
This will occur with every structural modification to any BP, node titles refresh only when visible.

[CL 2499923 by Michael Schoell in Main branch]
2015-04-02 11:16:23 -04:00

194 lines
6.5 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "BlueprintGraphPrivatePCH.h"
#include "CompilerResultsLog.h"
#include "BlueprintNodeSpawner.h"
#include "EditorCategoryUtils.h"
#include "Engine/InputAxisDelegateBinding.h"
#include "BlueprintActionDatabaseRegistrar.h"
#include "K2Node_InputAxisEvent.h"
#define LOCTEXT_NAMESPACE "K2Node_InputAxisEvent"
UK2Node_InputAxisEvent::UK2Node_InputAxisEvent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bConsumeInput = true;
bOverrideParentBinding = true;
bInternalEvent = true;
EventReference.SetExternalDelegateMember(FName(TEXT("InputAxisHandlerDynamicSignature__DelegateSignature")));
}
void UK2Node_InputAxisEvent::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
if(Ar.IsLoading())
{
if(Ar.UE4Ver() < VER_UE4_K2NODE_EVENT_MEMBER_REFERENCE && EventSignatureName_DEPRECATED.IsNone() && EventSignatureClass_DEPRECATED == nullptr)
{
EventReference.SetExternalDelegateMember(TEXT("InputAxisHandlerDynamicSignature__DelegateSignature"));
}
}
}
void UK2Node_InputAxisEvent::PostLoad()
{
Super::PostLoad();
if (GetLinkerUE4Version() < VER_UE4_BLUEPRINT_INPUT_BINDING_OVERRIDES)
{
// Don't change existing behaviors
bOverrideParentBinding = false;
}
}
void UK2Node_InputAxisEvent::Initialize(const FName AxisName)
{
InputAxisName = AxisName;
CustomFunctionName = FName( *FString::Printf(TEXT("InpAxisEvt_%s_%s"), *InputAxisName.ToString(), *GetName()));
}
FText UK2Node_InputAxisEvent::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
if (TitleType == ENodeTitleType::MenuTitle)
{
return FText::FromName(InputAxisName);
}
else if (CachedNodeTitle.IsOutOfDate(this))
{
FFormatNamedArguments Args;
Args.Add(TEXT("InputAxisName"), FText::FromName(InputAxisName));
FText LocFormat = NSLOCTEXT("K2Node", "InputAxis_Name", "InputAxis {InputAxisName}");
// FText::Format() is slow, so we cache this to save on performance
CachedNodeTitle.SetCachedText(FText::Format(LocFormat, Args), this);
}
return CachedNodeTitle;
}
FText UK2Node_InputAxisEvent::GetTooltipText() const
{
if (CachedTooltip.IsOutOfDate(this))
{
// FText::Format() is slow, so we cache this to save on performance
CachedTooltip.SetCachedText(FText::Format(NSLOCTEXT("K2Node", "InputAxis_Tooltip", "Event that provides the current value of the {0} axis once per frame when input is enabled for the containing actor."), FText::FromName(InputAxisName)), this);
}
return CachedTooltip;
}
void UK2Node_InputAxisEvent::ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const
{
Super::ValidateNodeDuringCompilation(MessageLog);
TArray<FName> AxisNames;
GetDefault<UInputSettings>()->GetAxisNames(AxisNames);
if (!AxisNames.Contains(InputAxisName))
{
MessageLog.Warning(*FString::Printf(*NSLOCTEXT("KismetCompiler", "MissingInputAxisEvent_Warning", "Input Axis Event references unknown Axis '%s' for @@").ToString(), *InputAxisName.ToString()), this);
}
}
UClass* UK2Node_InputAxisEvent::GetDynamicBindingClass() const
{
return UInputAxisDelegateBinding::StaticClass();
}
void UK2Node_InputAxisEvent::RegisterDynamicBinding(UDynamicBlueprintBinding* BindingObject) const
{
UInputAxisDelegateBinding* InputAxisBindingObject = CastChecked<UInputAxisDelegateBinding>(BindingObject);
FBlueprintInputAxisDelegateBinding Binding;
Binding.InputAxisName = InputAxisName;
Binding.bConsumeInput = bConsumeInput;
Binding.bExecuteWhenPaused = bExecuteWhenPaused;
Binding.bOverrideParentBinding = bOverrideParentBinding;
Binding.FunctionNameToBind = CustomFunctionName;
InputAxisBindingObject->InputAxisDelegateBindings.Add(Binding);
}
bool UK2Node_InputAxisEvent::IsCompatibleWithGraph(const UEdGraph* TargetGraph) const
{
// By default, to be safe, we don't allow events to be pasted, except under special circumstances (see below)
bool bIsCompatible = false;
// Find the Blueprint that owns the target graph
UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(TargetGraph);
if (Blueprint && Blueprint->SkeletonGeneratedClass)
{
bIsCompatible = Blueprint->ParentClass->IsChildOf(AActor::StaticClass());
}
return bIsCompatible && Super::IsCompatibleWithGraph(TargetGraph);
}
void UK2Node_InputAxisEvent::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
TArray<FName> AxisNames;
GetDefault<UInputSettings>()->GetAxisNames(AxisNames);
auto CustomizeInputNodeLambda = [](UEdGraphNode* NewNode, bool bIsTemplateNode, FName AxisName)
{
UK2Node_InputAxisEvent* InputNode = CastChecked<UK2Node_InputAxisEvent>(NewNode);
InputNode->Initialize(AxisName);
};
// actions get registered under specific object-keys; the idea is that
// actions might have to be updated (or deleted) if their object-key is
// mutated (or removed)... here we use the node's class (so if the node
// type disappears, then the action should go with it)
UClass* ActionKey = GetClass();
// to keep from needlessly instantiating a UBlueprintNodeSpawner, first
// check to make sure that the registrar is looking for actions of this type
// (could be regenerating actions for a specific asset, and therefore the
// registrar would only accept actions corresponding to that asset)
if (ActionRegistrar.IsOpenForRegistration(ActionKey))
{
auto RefreshClassActions = []()
{
FBlueprintActionDatabase::Get().RefreshClassActions(StaticClass());
};
static bool bRegisterOnce = true;
if(bRegisterOnce)
{
bRegisterOnce = false;
FEditorDelegates::OnActionAxisMappingsChanged.AddStatic(RefreshClassActions);
}
for (FName const AxisName : AxisNames)
{
UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
check(NodeSpawner != nullptr);
NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(CustomizeInputNodeLambda, AxisName);
ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
}
}
}
FText UK2Node_InputAxisEvent::GetMenuCategory() const
{
static FNodeTextCache CachedCategory;
if (CachedCategory.IsOutOfDate(this))
{
// FText::Format() is slow, so we cache this to save on performance
CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Input, LOCTEXT("ActionMenuCategory", "Axis Events")), this);
}
return CachedCategory;
}
FBlueprintNodeSignature UK2Node_InputAxisEvent::GetSignature() const
{
FBlueprintNodeSignature NodeSignature = Super::GetSignature();
NodeSignature.AddKeyValue(InputAxisName.ToString());
return NodeSignature;
}
#undef LOCTEXT_NAMESPACE