You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
This change consists of multiple changes: Core: - Deprecation of ANY_PACKAGE macro. Added ANY_PACKAGE_DEPRECATED macro which can still be used for backwards compatibility purposes (only used in CoreUObject) - Deprecation of StaticFindObjectFast* functions that take bAnyPackage parameter - Added UStruct::GetStructPathName function that returns FTopLevelAssetPath representing the path name (package + object FName, super quick compared to UObject::GetPathName) + wrapper UClass::GetClassPathName to make it look better when used with UClasses - Added (Static)FindFirstObject* functions that find a first object given its Name (no Outer). These functions are used in places I consider valid to do global UObject (UClass) lookups like parsing command line parameters / checking for unique object names - Added static UClass::TryFindType function which serves a similar purpose as FindFirstObject however it's going to throw a warning (with a callstack / maybe ensure in the future?) if short class name is provided. This function is used in places that used to use short class names but now should have been converted to use path names to catch any potential regressions and or edge cases I missed. - Added static UClass::TryConvertShortNameToPathName utility function - Added static UClass::TryFixShortClassNameExportPath utility function - Object text export paths will now also include class path (Texture2D'/Game/Textures/Grass.Grass' -> /Script/Engine.Texture2D'/Game/Textures/Grass.Grass') - All places that manually generated object export paths for objects will now use FObjectPropertyBase::GetExportPath - Added a new startup test that checks for short type names in UClass/FProperty MetaData values AssetRegistry: - Deprecated any member variables (FAssetData / FARFilter) or functions that use FNames to represent class names and replaced them with FTopLevelAssetPath - Added new member variables and new function overloads that use FTopLevelAssetPath to represent class names - This also applies to a few other modules' APIs to match AssetRegistry changes Everything else: - Updated code that used ANY_PACKAGE (depending on the use case) to use FindObject(nullptr, PathToObject), UClass::TryFindType (used when path name is expected, warns if it's a short name) or FindFirstObject (usually for finding types based on user input but there's been a few legitimate use cases not related to user input) - Updated code that used AssetRegistry API to use FTopLevelAssetPaths and USomeClass::StaticClass()->GetClassPathName() instead of GetFName() - Updated meta data and hardcoded FindObject(ANY_PACKAGE, "EEnumNameOrClassName") calls to use path names #jira UE-99463 #rb many.people [FYI] Marcus.Wassmer #preflight 629248ec2256738f75de9b32 #codereviewnumbers 20320742, 20320791, 20320799, 20320756, 20320809, 20320830, 20320840, 20320846, 20320851, 20320863, 20320780, 20320765, 20320876, 20320786 #ROBOMERGE-OWNER: robert.manuszewski #ROBOMERGE-AUTHOR: robert.manuszewski #ROBOMERGE-SOURCE: CL 20430220 via CL 20433854 via CL 20435474 via CL 20435484 #ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v949-20362246) [CL 20448496 by robert manuszewski in ue5-main branch]
435 lines
19 KiB
C++
435 lines
19 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "BlueprintEditorCommands.h"
|
|
#include "EdGraph/EdGraphNode.h"
|
|
#include "Engine/Blueprint.h"
|
|
#include "EdGraph/EdGraphSchema.h"
|
|
#include "UObject/UnrealType.h"
|
|
#include "Engine/LevelScriptActor.h"
|
|
#include "UObject/UObjectHash.h"
|
|
#include "Engine/Selection.h"
|
|
#include "Editor.h"
|
|
#include "EdGraphSchema_K2.h"
|
|
#include "K2Node_Literal.h"
|
|
#include "K2Node_MacroInstance.h"
|
|
#include "Kismet2/BlueprintEditorUtils.h"
|
|
#include "BlueprintNodeBinder.h"
|
|
#include "BlueprintNodeSpawner.h"
|
|
#include "BlueprintFunctionNodeSpawner.h"
|
|
#include "UObject/UObjectIterator.h"
|
|
#include "BlueprintEventNodeSpawner.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "BlueprintEditorCommands"
|
|
|
|
/** UI_COMMAND takes long for the compile to optimize */
|
|
PRAGMA_DISABLE_OPTIMIZATION
|
|
void FBlueprintEditorCommands::RegisterCommands()
|
|
{
|
|
// Edit commands
|
|
UI_COMMAND( FindInBlueprint, "Find", "Finds references to functions, events, variables, and pins in the current Blueprint (use Ctrl+Shift+F to search in all Blueprints)", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Control, EKeys::F) );
|
|
UI_COMMAND( FindInBlueprints, "Find in Blueprints", "Find references to functions, events and variables in ALL Blueprints", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Control | EModifierKey::Shift, EKeys::F) );
|
|
UI_COMMAND( ReparentBlueprint, "Reparent Blueprint", "Change the parent of this Blueprint", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( CompileBlueprint, "Compile", "Compile the blueprint", EUserInterfaceActionType::Button, FInputChord(EKeys::F7) );
|
|
UI_COMMAND( RefreshAllNodes, "Refresh All nodes", "Refreshes all nodes in the graph to account for external changes", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( DeleteUnusedVariables, "Delete Unused Variables", "Deletes any variables that are never used", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( FindReferencesFromClass, "List references (from class)", "Find all objects that the class references", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( FindReferencesFromBlueprint, "List referenced (from blueprint)", "Find all objects that the blueprint references", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( RepairCorruptedBlueprint, "Repair corrupted blueprint", "Attempts to repair a corrupted blueprint that cannot be saved", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
// View commands
|
|
UI_COMMAND( ZoomToWindow, "Zoom to Graph Extents", "Fit the current view to the entire graph", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ZoomToSelection, "Zoom to Selection", "Fit the current view to the selection", EUserInterfaceActionType::Button, FInputChord(EKeys::Home) );
|
|
UI_COMMAND( NavigateToParent, "Go to parent graph", "Open the parent graph", EUserInterfaceActionType::Button, FInputChord(EKeys::PageUp) );
|
|
UI_COMMAND( NavigateToParentBackspace, "Go to parent graph", "Open the parent graph", EUserInterfaceActionType::Button, FInputChord(EKeys::BackSpace) );
|
|
UI_COMMAND( NavigateToChild, "Go to child graph", "Open the child graph", EUserInterfaceActionType::Button, FInputChord(EKeys::PageDown) );
|
|
|
|
// Preview commands
|
|
UI_COMMAND( ResetCamera, "Reset Camera", "Resets the camera to focus on the mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( EnableSimulation, "Simulation", "Enables simulation of components in the viewport", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ShowFloor, "Show Floor", "Toggles a ground mesh for collision", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ShowGrid, "Show Grid", "Toggles viewport grid", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
|
|
// Debugging commands
|
|
UI_COMMAND( EnableAllBreakpoints,"Enable All Breakpoints", "Enable all breakpoints", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( DisableAllBreakpoints, "Disable All Breakpoints", "Disable all breakpoints", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ClearAllBreakpoints, "Delete All Breakpoints", "Delete all breakpoints", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Control | EModifierKey::Shift, EKeys::F9) );
|
|
UI_COMMAND( ClearAllWatches, "Delete All Watches", "Delete all watches", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( OpenBlueprintDebugger, "Blueprint Debugger", "Open the Blueprint Debugger tab.", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
// New documents
|
|
UI_COMMAND( AddNewVariable, "Variable", "Adds a new variable to this blueprint.", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddNewLocalVariable, "Local Variable", "Adds a new local variable to this graph.", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddNewFunction, "Function", "Add a new function graph", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddNewMacroDeclaration, "Macro", "Add a new macro declaration graph", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddNewAnimationLayer, "Animation Layer", "Add a new animation layer", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddNewEventGraph, "Graph", "Add a new event graph", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddNewDelegate, "Event Dispatcher", "Add a new event dispatcher", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
// Development commands
|
|
UI_COMMAND( SaveIntermediateBuildProducts, "Save Intermediate Build Products", "Should the compiler save intermediate build products for debugging.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND(GenerateSearchIndex, "Generate Search Index", "Generate the search index for this blueprint.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND(DumpCachedIndexData, "Dump Cached Index Data", "Dump the cached index data for this blueprint.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND(ShowActionMenuItemSignatures, "Show Action Menu Item Signatures", "If enabled, tooltips on action menu items will show the associated action's signature id (can be used to setup custom favorites menus).", EUserInterfaceActionType::ToggleButton, FInputChord());
|
|
|
|
// SCC commands
|
|
UI_COMMAND( BeginBlueprintMerge, "Merge", "Shows the Blueprint merge panel and toolbar, allowing the user to resolve conflicted blueprints", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
// Hide unrelated nodes
|
|
UI_COMMAND( ToggleHideUnrelatedNodes, "Hide Unrelated", "Toggles automatically hiding nodes which are unrelated to the selected nodes.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
}
|
|
|
|
PRAGMA_ENABLE_OPTIMIZATION
|
|
|
|
namespace NodeSpawnInfoHelpers
|
|
{
|
|
/**
|
|
* Checks if the passed in function is available as an event for the Blueprint
|
|
*
|
|
* @param InBlueprint The Blueprint to check for validity with
|
|
* @param InFunction The Function to check for being available as an event
|
|
*
|
|
* @return Returns true if the function is available as an event in the Blueprint
|
|
*/
|
|
bool IsFunctionAvailableAsEvent(const UBlueprint* InBlueprint, const UFunction* InFunction)
|
|
{
|
|
// Build a list of all interface classes either implemented by this blueprint or through inheritance
|
|
TArray<UClass*> InterfaceClasses;
|
|
FBlueprintEditorUtils::FindImplementedInterfaces(InBlueprint, true, InterfaceClasses);
|
|
InterfaceClasses.Add(InBlueprint->ParentClass);
|
|
|
|
// Grab the list of events to be excluded from the override list
|
|
const FString ExclusionListKeyName = TEXT("KismetHideOverrides");
|
|
TArray<FString> ExcludedEventNames;
|
|
if( InBlueprint->ParentClass->HasMetaData(*ExclusionListKeyName) )
|
|
{
|
|
const FString& ExcludedEventNameString = InBlueprint->ParentClass->GetMetaData(*ExclusionListKeyName);
|
|
ExcludedEventNameString.ParseIntoArray(ExcludedEventNames, TEXT(","), true);
|
|
}
|
|
|
|
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
|
if (K2Schema->FunctionCanBePlacedAsEvent(InFunction) && !ExcludedEventNames.Contains(InFunction->GetName()))
|
|
{
|
|
// Check all potential interface events using the class list we build above
|
|
for(auto It = InterfaceClasses.CreateConstIterator(); It; It++)
|
|
{
|
|
const UClass* Interface = (*It);
|
|
for (TFieldIterator<UFunction> FunctionIt(Interface, EFieldIteratorFlags::IncludeSuper); FunctionIt; ++FunctionIt)
|
|
{
|
|
UFunction* Function = *FunctionIt;
|
|
|
|
if(Function->GetName() == InFunction->GetName())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Finds the event version of a UFunction for a given Blueprint
|
|
*
|
|
* @param InBlueprint The Blueprint to find the function within
|
|
* @param InFunction The Function to find an event version of
|
|
*
|
|
* @return Event Function used by the given Blueprint for the given Function
|
|
*/
|
|
UFunction* FindEventFunctionForClass(const UBlueprint* InBlueprint, const UFunction* InFunction)
|
|
{
|
|
// Look at all of the Blueprint parent's functions for an event
|
|
for (TFieldIterator<UFunction> FunctionIt(InBlueprint->ParentClass, EFieldIteratorFlags::IncludeSuper); FunctionIt; ++FunctionIt)
|
|
{
|
|
UFunction* Function = *FunctionIt;
|
|
if(Function->GetName() == InFunction->GetName())
|
|
{
|
|
return Function;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
class FNodeSpawnInfo
|
|
{
|
|
public:
|
|
virtual ~FNodeSpawnInfo () {}
|
|
|
|
/** Holds the UI Command to verify chords for this action are held */
|
|
TSharedPtr< FUICommandInfo > CommandInfo;
|
|
|
|
/**
|
|
* Creates an action to be used for placing a node into the graph
|
|
*
|
|
* @param InDestGraph The graph the action should be created for
|
|
* @param InOutDestPosition Position to start placing nodes, will be updated to be at the next safe position for node placement
|
|
* @param OutNodes All nodes spawned by this operation
|
|
*
|
|
* @return A fully prepared action containing the information to spawn the node
|
|
*/
|
|
virtual void GetActions(UEdGraph* InDestGraph, FVector2D& InOutDestPosition, TArray<UEdGraphNode*>& OutNodes) = 0;
|
|
};
|
|
|
|
class FEdGraphNodeSpawnInfo : public FNodeSpawnInfo
|
|
{
|
|
public:
|
|
FEdGraphNodeSpawnInfo(UClass* InClass) : NodeClass(InClass) {}
|
|
|
|
// FNodeSpawnInfo interface
|
|
virtual void GetActions(UEdGraph* InDestGraph, FVector2D& InOutDestPosition, TArray<UEdGraphNode*>& OutNodes) override
|
|
{
|
|
TSharedPtr<FEdGraphSchemaAction_NewNode> NewActionNode = TSharedPtr<FEdGraphSchemaAction_NewNode>(new FEdGraphSchemaAction_NewNode);
|
|
|
|
IBlueprintNodeBinder::FBindingSet Bindings;
|
|
UEdGraphNode* GraphNode = UBlueprintNodeSpawner::Create(NodeClass)->Invoke(InDestGraph, Bindings, InOutDestPosition);
|
|
|
|
InOutDestPosition.Y = FMath::Max(InOutDestPosition.Y, GraphNode->NodePosY + UEdGraphSchema_K2::EstimateNodeHeight(GraphNode));
|
|
OutNodes.Add(GraphNode);
|
|
}
|
|
// End of FNodeSpawnInfo interface
|
|
|
|
private:
|
|
/** The class type the node should be */
|
|
UClass* NodeClass;
|
|
};
|
|
|
|
class FFunctionNodeSpawnInfo : public FNodeSpawnInfo
|
|
{
|
|
public:
|
|
FFunctionNodeSpawnInfo(UFunction* InFunctionPtr) : FunctionPtr(InFunctionPtr) {}
|
|
|
|
// FNodeSpawnInfo interface
|
|
virtual void GetActions(UEdGraph* InDestGraph, FVector2D& InOutDestPosition, TArray<UEdGraphNode*>& OutNodes) override
|
|
{
|
|
const UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(InDestGraph);
|
|
|
|
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
|
if(NodeSpawnInfoHelpers::IsFunctionAvailableAsEvent(Blueprint, FunctionPtr))
|
|
{
|
|
UFunction* FunctionEvent = NodeSpawnInfoHelpers::FindEventFunctionForClass(Blueprint, FunctionPtr);
|
|
if(FunctionEvent)
|
|
{
|
|
IBlueprintNodeBinder::FBindingSet Bindings;
|
|
UEdGraphNode* GraphNode = UBlueprintEventNodeSpawner::Create(FunctionEvent)->Invoke(InDestGraph, Bindings, InOutDestPosition);
|
|
|
|
InOutDestPosition.Y = FMath::Max(InOutDestPosition.Y, GraphNode->NodePosY + UEdGraphSchema_K2::EstimateNodeHeight(GraphNode));
|
|
OutNodes.Add(GraphNode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const bool bAllowImpureFuncs = K2Schema->DoesGraphSupportImpureFunctions(InDestGraph);
|
|
|
|
uint32 FunctionTypes = UEdGraphSchema_K2::EFunctionType::FT_Pure | UEdGraphSchema_K2::EFunctionType::FT_Const | UEdGraphSchema_K2::EFunctionType::FT_Protected;
|
|
if(bAllowImpureFuncs)
|
|
{
|
|
FunctionTypes |= UEdGraphSchema_K2::EFunctionType::FT_Imperative;
|
|
}
|
|
|
|
if(K2Schema->CanFunctionBeUsedInGraph(Blueprint->GeneratedClass, FunctionPtr, InDestGraph, FunctionTypes, false))
|
|
{
|
|
IBlueprintNodeBinder::FBindingSet Bindings;
|
|
UEdGraphNode* GraphNode = UBlueprintFunctionNodeSpawner::Create(FunctionPtr)->Invoke(InDestGraph, Bindings, InOutDestPosition);
|
|
|
|
InOutDestPosition.Y = FMath::Max(InOutDestPosition.Y, GraphNode->NodePosY + UEdGraphSchema_K2::EstimateNodeHeight(GraphNode));
|
|
OutNodes.Add(GraphNode);
|
|
}
|
|
}
|
|
}
|
|
// End of FNodeSpawnInfo interface
|
|
|
|
private:
|
|
/** The function used to create the action to spawn the graph node */
|
|
UFunction* FunctionPtr;
|
|
};
|
|
|
|
class FMacroNodeSpawnInfo : public FNodeSpawnInfo
|
|
{
|
|
public:
|
|
FMacroNodeSpawnInfo(UEdGraph* InMacroGraph) : MacroGraph(InMacroGraph) {}
|
|
|
|
// FNodeSpawnInfo interface
|
|
virtual void GetActions(UEdGraph* InDestGraph, FVector2D& InOutDestPosition, TArray<UEdGraphNode*>& OutNodes) override
|
|
{
|
|
IBlueprintNodeBinder::FBindingSet Bindings;
|
|
UK2Node_MacroInstance* MacroInstanceNode = Cast<UK2Node_MacroInstance>(UBlueprintNodeSpawner::Create(UK2Node_MacroInstance::StaticClass())->Invoke(InDestGraph, Bindings, InOutDestPosition));
|
|
MacroInstanceNode->SetMacroGraph(MacroGraph);
|
|
MacroInstanceNode->ReconstructNode();
|
|
OutNodes.Add(MacroInstanceNode);
|
|
}
|
|
// End of FNodeSpawnInfo interface
|
|
|
|
private:
|
|
/** The macro graph used to create the action to spawn the graph node */
|
|
UEdGraph* MacroGraph;
|
|
};
|
|
|
|
class FActorRefSpawnInfo : public FNodeSpawnInfo
|
|
{
|
|
public:
|
|
// FNodeSpawnInfo interface
|
|
virtual void GetActions(UEdGraph* InDestGraph, FVector2D& InOutDestPosition, TArray<UEdGraphNode*>& OutNodes) override
|
|
{
|
|
const UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(InDestGraph);
|
|
USelection* SelectedLvlActors = GEditor->GetSelectedActors();
|
|
|
|
if ((Blueprint != nullptr) && Blueprint->ParentClass->IsChildOf<ALevelScriptActor>() && (SelectedLvlActors->Num() > 0))
|
|
{
|
|
for (FSelectionIterator LvlActorIt(*SelectedLvlActors); LvlActorIt; ++LvlActorIt)
|
|
{
|
|
IBlueprintNodeBinder::FBindingSet Bindings;
|
|
UK2Node_Literal* TemplateRefNode = Cast<UK2Node_Literal>(UBlueprintNodeSpawner::Create(UK2Node_Literal::StaticClass())->Invoke(InDestGraph, Bindings, InOutDestPosition));
|
|
TemplateRefNode->SetObjectRef(*LvlActorIt);
|
|
|
|
OutNodes.Add(TemplateRefNode);
|
|
}
|
|
}
|
|
}
|
|
// End of FNodeSpawnInfo interface
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FBlueprintSpawnNodeCommands
|
|
|
|
void FBlueprintSpawnNodeCommands::RegisterCommands()
|
|
{
|
|
const FString ConfigSection = TEXT("BlueprintSpawnNodes");
|
|
const FString SettingName = TEXT("Node");
|
|
TArray< FString > NodeSpawns;
|
|
GConfig->GetArray(*ConfigSection, *SettingName, NodeSpawns, GEditorPerProjectIni);
|
|
|
|
for(int32 x = 0; x < NodeSpawns.Num(); ++x)
|
|
{
|
|
FString ClassName;
|
|
if(!FParse::Value(*NodeSpawns[x], TEXT("Class="), ClassName))
|
|
{
|
|
// Could not find a class name, cannot continue with this line
|
|
continue;
|
|
}
|
|
|
|
UE_CLOG(FPackageName::IsShortPackageName(ClassName), LogClass, Warning, TEXT("Short class name found when parsing ini: [%s] %s"), *ConfigSection, *SettingName);
|
|
|
|
FString CommandLabel;
|
|
UClass* FoundClass = FindFirstObject<UClass>(*ClassName, EFindFirstObjectOptions::ExactClass, ELogVerbosity::Warning, TEXT("looking for SpawnNodes"));
|
|
TSharedPtr< FNodeSpawnInfo > InfoPtr;
|
|
|
|
if(FoundClass && FoundClass->IsChildOf(UEdGraphNode::StaticClass()))
|
|
{
|
|
// The class name matches that of a UEdGraphNode, so setup a spawn info that can generate UEdGraphNode graph actions
|
|
UEdGraphNode* GraphNode = Cast<UEdGraphNode>(FoundClass->GetDefaultObject());
|
|
|
|
CommandLabel = GraphNode->GetNodeTitle(ENodeTitleType::ListView).ToString();
|
|
|
|
if(CommandLabel.Len() == 0)
|
|
{
|
|
CommandLabel = FoundClass->GetName();
|
|
}
|
|
|
|
InfoPtr = MakeShareable( new FEdGraphNodeSpawnInfo( FoundClass ) );
|
|
}
|
|
else if(UFunction* FoundFunction = FindFirstObject<UFunction>(*ClassName, EFindFirstObjectOptions::ExactClass, ELogVerbosity::Warning, TEXT("looking for SpawnNodes (function)")))
|
|
{
|
|
// The class name matches that of a function, so setup a spawn info that can generate function graph actions
|
|
InfoPtr = MakeShareable( new FFunctionNodeSpawnInfo((UFunction*)FoundFunction));
|
|
|
|
CommandLabel = FoundFunction->GetName();
|
|
}
|
|
else
|
|
{
|
|
// Check for a macro graph that matches the passed in class name
|
|
for (TObjectIterator<UBlueprint> BlueprintIt; BlueprintIt; ++BlueprintIt)
|
|
{
|
|
UBlueprint* MacroBP = *BlueprintIt;
|
|
if(MacroBP->BlueprintType == BPTYPE_MacroLibrary)
|
|
{
|
|
// getting 'top-level' of the macros
|
|
for (TArray<UEdGraph*>::TIterator GraphIt(MacroBP->MacroGraphs); GraphIt; ++GraphIt)
|
|
{
|
|
UEdGraph* MacroGraph = *GraphIt;
|
|
// The class name matches that of a macro, so setup a spawn info that can generate macro graph actions
|
|
if(MacroGraph->GetName() == ClassName)
|
|
{
|
|
CommandLabel = MacroGraph->GetName();
|
|
|
|
InfoPtr = MakeShareable( new FMacroNodeSpawnInfo(MacroGraph));
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If spawn info was created, setup a UI Command for keybinding.
|
|
if(InfoPtr.IsValid())
|
|
{
|
|
TSharedPtr< FUICommandInfo > CommandInfo;
|
|
|
|
FKey Key;
|
|
bool bShift = false;
|
|
bool bCtrl = false;
|
|
bool bAlt = false;
|
|
bool bCmd = false;
|
|
|
|
// Parse the keybinding information
|
|
FString KeyString;
|
|
if( FParse::Value(*NodeSpawns[x], TEXT("Key="), KeyString) )
|
|
{
|
|
Key = *KeyString;
|
|
}
|
|
|
|
if( Key.IsValid() )
|
|
{
|
|
FParse::Bool(*NodeSpawns[x], TEXT("Shift="), bShift);
|
|
FParse::Bool(*NodeSpawns[x], TEXT("Alt="), bAlt);
|
|
FParse::Bool(*NodeSpawns[x], TEXT("Ctrl="), bCtrl);
|
|
FParse::Bool(*NodeSpawns[x], TEXT("Cmd="), bCmd);
|
|
}
|
|
|
|
FInputChord Chord(Key, EModifierKey::FromBools(bCtrl, bAlt, bShift, bCmd));
|
|
|
|
FText CommandLabelText = FText::FromString( CommandLabel );
|
|
FText Description = FText::Format( NSLOCTEXT("BlueprintEditor", "NodeSpawnDescription", "Hold down the bound keys and left click in the graph panel to spawn a {0} node."), CommandLabelText );
|
|
|
|
FUICommandInfo::MakeCommandInfo( this->AsShared(), CommandInfo, FName(*NodeSpawns[x]), CommandLabelText, Description, FSlateIcon(FAppStyle::GetAppStyleSetName(), *FString::Printf(TEXT("%s.%s"), *this->GetContextName().ToString(), *NodeSpawns[x])), EUserInterfaceActionType::Button, Chord );
|
|
|
|
InfoPtr->CommandInfo = CommandInfo;
|
|
|
|
NodeCommands.Add(InfoPtr);
|
|
}
|
|
}
|
|
|
|
TSharedPtr<FNodeSpawnInfo> AddActorRefAction = MakeShareable(new FActorRefSpawnInfo);
|
|
UI_COMMAND(AddActorRefAction->CommandInfo, "Add Selected Actor Reference(s)", "Spawns node(s) which reference the currently selected actor(s) in the level.", EUserInterfaceActionType::Button, FInputChord(EKeys::R));
|
|
NodeCommands.Add(AddActorRefAction);
|
|
}
|
|
|
|
|
|
void FBlueprintSpawnNodeCommands::GetGraphActionByChord(FInputChord& InChord, UEdGraph* InDestGraph, FVector2D& InOutDestPosition, TArray<UEdGraphNode*>& OutNodes) const
|
|
{
|
|
if(InChord.IsValidChord())
|
|
{
|
|
for(int32 x = 0; x < NodeCommands.Num(); ++x)
|
|
{
|
|
if(NodeCommands[x]->CommandInfo->HasActiveChord(InChord))
|
|
{
|
|
NodeCommands[x]->GetActions(InDestGraph, InOutDestPosition, OutNodes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FSCSEditorViewportCommands
|
|
|
|
void FSCSEditorViewportCommands::RegisterCommands()
|
|
{
|
|
UI_COMMAND(DeleteComponent, "Delete", "Delete current selection", EUserInterfaceActionType::Button, FInputChord(EKeys::Platform_Delete));
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|