DebugExecBindings
DebugExecBindings
#Overview
name: DebugExecBindings
The value of this variable can be defined or overridden in .ini config files. 25
.ini config files referencing this setting variable.
It is referenced in 9
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of DebugExecBindings is to provide a mechanism for binding keys to debug commands in Unreal Engine. This variable is primarily used for development and debugging purposes, allowing developers to execute specific commands or actions by pressing designated keys during runtime.
DebugExecBindings is primarily used in the Engine module, specifically within the PlayerInput system. It’s also utilized by various developer plugins such as the RenderDoc Plugin and Xcode GPU Debugger Plugin.
The value of this variable is set in multiple ways:
- Through configuration files (as seen in the RenderDocPlugin and XcodeGPUDebuggerPlugin modules)
- Dynamically at runtime through the SetBind function in PlayerInput
DebugExecBindings interacts with other input-related variables and systems within the PlayerInput class, such as ActionMappings and AxisConfig.
Developers should be aware of the following when using this variable:
- It’s intended for development and debugging purposes, not for shipping game features.
- The bindings are stored in the config files, so they persist between editor sessions.
- These bindings can be modified at runtime, which can be powerful but also potentially confusing if not managed properly.
Best practices when using DebugExecBindings include:
- Use clear, descriptive command names to make the purpose of each binding obvious.
- Be cautious when adding or modifying bindings to avoid conflicts with existing game controls.
- Consider using modifier keys (Shift, Alt, Ctrl) to reduce the likelihood of accidental triggers.
- Remove or disable debug bindings before shipping the final product to end-users.
- Document any custom debug bindings used in the project for other team members.
#Setting Variables
#References In INI files
<Workspace>/Engine/Config/BaseInput.ini:38, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:39, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:40, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:41, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:42, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:43, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:44, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:45, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:46, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:47, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:48, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:49, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:50, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:51, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:52, section: [/Script/Engine.PlayerInput]
<Workspace>/Engine/Config/BaseInput.ini:54, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:2, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:3, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:4, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:5, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:6, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:7, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:8, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:9, section: [/Script/Engine.PlayerInput]
<Workspace>/Projects/Lyra/Config/DefaultInput.ini:10, section: [/Script/Engine.PlayerInput]
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Developer/RenderDocPlugin/Source/RenderDocPlugin/Private/RenderDocPluginModule.cpp:375
Scope (from outer to inner):
file
function void FRenderDocPluginModule::InjectDebugExecKeybind
Source code excerpt:
{
// Inject our key bind into the debug execs
GConfig->AddUniqueToSection(TEXT("/Script/Engine.PlayerInput"), TEXT("DebugExecBindings"), TEXT("(Key=F12,Command=\"RenderDoc.CaptureFrame\", Alt=true)"), GInputIni);
}
void FRenderDocPluginModule::EndFrameCapture(void* HWnd, uint32 Flags, const FString& DestFileName)
{
HWND WindowHandle = (HWnd) ? reinterpret_cast<HWND>(HWnd) : GetActiveWindow();
#Loc: <Workspace>/Engine/Plugins/Developer/XcodeGPUDebuggerPlugin/Source/XcodeGPUDebuggerPlugin/Private/XcodeGPUDebuggerPluginModule.cpp:221
Scope (from outer to inner):
file
function void FXcodeGPUDebuggerPluginModule::InjectDebugExecKeybind
Source code excerpt:
void FXcodeGPUDebuggerPluginModule::InjectDebugExecKeybind()
{
GConfig->AddUniqueToSection(TEXT("/Script/Engine.PlayerInput"), TEXT("DebugExecBindings"), TEXT("(Key=E,Command=\"Xcode.CaptureFrame\", Shift=true)"), GInputIni);
}
void FXcodeGPUDebuggerPluginModule::EndFrameCapture(void* HWnd, uint32 Flags, const FString& DestFileName)
{
ENQUEUE_RENDER_COMMAND(EndXcodeGPUDebuggerCapture)(
[Plugin = this, Flags, DestFileName](FRHICommandListImmediate& RHICmdList)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/GameFramework/PlayerInput.h:434
Scope (from outer to inner):
file
class class UPlayerInput : public UObject
Source code excerpt:
/** Generic bindings of keys to Exec()-compatible strings for development purposes only */
UPROPERTY(config)
TArray<struct FKeyBind> DebugExecBindings;
/** This player's version of the Axis Properties */
TArray<struct FInputAxisConfigEntry> AxisConfig;
/** This player's version of the Action Mappings */
TArray<struct FInputActionKeyMapping> ActionMappings;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UserInterface/PlayerInput.cpp:2237
Scope (from outer to inner):
file
function bool UPlayerInput::Exec
Source code excerpt:
if (Key.IsValid())
{
for(uint32 BindIndex = 0;BindIndex < (uint32)DebugExecBindings.Num();BindIndex++)
{
if (DebugExecBindings[BindIndex].Key == Key)
{
Ar.Logf(TEXT("%s"),*DebugExecBindings[BindIndex].Command);
break;
}
}
}
return 1;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UserInterface/PlayerInput.cpp:2254
Scope (from outer to inner):
file
function bool UPlayerInput::Exec
Source code excerpt:
if(Key.IsValid())
{
for(int32 BindIndex = DebugExecBindings.Num() - 1; BindIndex >= 0; BindIndex--)
{
if(DebugExecBindings[BindIndex].Key == Key)
{
bExecutingBindCommand = true;
bool bResult = ExecInputCommands(GetWorld(), *DebugExecBindings[BindIndex].Command,Ar);
bExecutingBindCommand = false;
return bResult;
}
}
}
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UserInterface/PlayerInput.cpp:2281
Scope (from outer to inner):
file
function FString UPlayerInput::GetBind
Source code excerpt:
const bool bCmdPressed = IsCmdPressed();
for ( int32 BindIndex = DebugExecBindings.Num() - 1; BindIndex >= 0; BindIndex-- )
{
const FKeyBind& Bind = DebugExecBindings[BindIndex];
if ( Bind.Key == Key && !Bind.bDisabled )
{
// if the modifier key pressed [or this key-bind doesn't require that key], and the key-bind isn't
// configured to ignore they modifier key, we've found a match.
if ((!Bind.Control || bControlPressed) && (!Bind.Shift || bShiftPressed) && (!Bind.Alt || bAltPressed) && (!Bind.Cmd || bCmdPressed)
&& (!Bind.bIgnoreCtrl || !bControlPressed) && (!Bind.bIgnoreShift || !bShiftPressed) && (!Bind.bIgnoreAlt || !bAltPressed) && (!Bind.bIgnoreCmd || !bCmdPressed))
{
return DebugExecBindings[BindIndex].Command;
}
}
}
}
return TEXT("");
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UserInterface/PlayerInput.cpp:2303
Scope (from outer to inner):
file
function FKeyBind UPlayerInput::GetExecBind
Source code excerpt:
{
FKeyBind Binding;
for( auto InputBindingIt = DebugExecBindings.CreateConstIterator(); InputBindingIt; ++InputBindingIt )
{
if(InputBindingIt->Command == ExecCommand)
{
Binding = *InputBindingIt;
break;
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UserInterface/PlayerInput.cpp:2327
Scope (from outer to inner):
file
function void UPlayerInput::SetBind
Source code excerpt:
}
for(int32 BindIndex = DebugExecBindings.Num()-1;BindIndex >= 0;BindIndex--)
{
if (DebugExecBindings[BindIndex].Key == BindKey)
{
DebugExecBindings[BindIndex].Command = CommandMod;
SaveConfig();
return;
}
}
FKeyBind NewBind;
NewBind.Key = BindKey;
NewBind.Command = CommandMod;
DebugExecBindings.Add(NewBind);
SaveConfig();
}
#endif
}
class UWorld* UPlayerInput::GetWorld() const
#Loc: <Workspace>/Engine/Source/Runtime/GameplayDebugger/Private/GameplayDebuggerLocalController.cpp:568
Scope (from outer to inner):
file
function void UGameplayDebuggerLocalController::BindInput
Source code excerpt:
UPlayerInput* Input = CachedReplicator->GetReplicationOwner()->PlayerInput;
for (int32 Idx = 0; Idx < Input->DebugExecBindings.Num(); Idx++)
{
FKeyBind& DebugBinding = Input->DebugExecBindings[Idx];
const bool bRemoveMask = RemovedMasks.Contains(DebugBinding.Key.GetFName());
const bool bAddMask = AddedMasks.Contains(DebugBinding.Key.GetFName());
if (bAddMask || bRemoveMask)
{
DebugBinding.bDisabled = bAddMask;