Created
April 17, 2025 21:51
-
-
Save jeremyabel/d3ac8054b72466cc531c9cfe203f2453 to your computer and use it in GitHub Desktop.
Slate Widget Input Debug Panel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright Feral Cat Den, LLC. All Rights Reserved. | |
#include "GNInputEventDebugger.h" | |
#if WITH_GN_DEBUGGER && WITH_SLATE_DEBUGGING | |
#include "Debugging/SlateDebugging.h" | |
#include "Development/GNDebugImGuiCommon.h" | |
#include "UI/GNWidgetStatics.h" | |
FGNInputEventDebugger::FGNInputEventDebugger() | |
: bEnabled(false) | |
, bDebuggerInputEnabled(true) | |
, MaxInputHistoryEntries(50) | |
, ProcessInputCounter(0) | |
, RouteInputCounter(0) | |
, EnabledInputEvents(false, (uint8)ESlateDebuggingInputEvent::MAX) | |
{ | |
EnabledInputEvents[(uint8)ESlateDebuggingInputEvent::MouseButtonDown] = true; | |
EnabledInputEvents[(uint8)ESlateDebuggingInputEvent::MouseButtonUp] = true; | |
EnabledInputEvents[(uint8)ESlateDebuggingInputEvent::MouseButtonDoubleClick] = true; | |
EnabledInputEvents[(uint8)ESlateDebuggingInputEvent::KeyDown] = true; | |
EnabledInputEvents[(uint8)ESlateDebuggingInputEvent::KeyUp] = true; | |
} | |
FGNInputEventDebugger::~FGNInputEventDebugger() | |
{ | |
StopDebugging(); | |
} | |
void FGNInputEventDebugger::StartDebugging() | |
{ | |
if (!bEnabled) | |
{ | |
bEnabled = true; | |
FSlateDebugging::RegisterWidgetInputRoutingEvent(this); | |
} | |
} | |
void FGNInputEventDebugger::StopDebugging() | |
{ | |
if (bEnabled) | |
{ | |
bEnabled = false; | |
FSlateDebugging::UnregisterWidgetInputRoutingEvent(this); | |
InputHistoryEntries.Reset(); | |
ProcessInputCounter = 0; | |
RouteInputCounter = 0; | |
} | |
} | |
TConstArrayView<TSharedRef<FGNInputSlateHistoryEntry>> FGNInputEventDebugger::GetHistoryEntriesView() const | |
{ | |
return TConstArrayView<TSharedRef<FGNInputSlateHistoryEntry>>(InputHistoryEntries); | |
} | |
void FGNInputEventDebugger::OnProcessInput(ESlateDebuggingInputEvent InputEventType, const FInputEvent& Event) | |
{ | |
if (!bDebuggerInputEnabled && EnabledInputEvents[(uint8)InputEventType]) | |
{ | |
TSharedRef<FGNInputSlateHistoryEntry> NewEntry = MakeShared<FGNInputSlateHistoryEntry>(); | |
NewEntry->EntryType = EGNInputSlateHistoryEntryType::Process; | |
NewEntry->EventType = InputEventType; | |
NewEntry->Info += StaticEnum<ESlateDebuggingInputEvent>()->GetDisplayNameTextByValue((int64)InputEventType).ToString(); | |
NewEntry->Info += TEXT(" - "); | |
NewEntry->Info += Event.ToText().ToString(); | |
NewEntry->bIsVerbose = false; | |
InputHistoryEntries.Add(NewEntry); | |
} | |
++ProcessInputCounter; | |
} | |
void FGNInputEventDebugger::OnPreProcessInput(ESlateDebuggingInputEvent InputEventType, const TCHAR* InputPrecessor, bool bHandled) | |
{ | |
if (!bDebuggerInputEnabled && EnabledInputEvents[(uint8)InputEventType]) | |
{ | |
TSharedRef<FGNInputSlateHistoryEntry> NewEntry = MakeShared<FGNInputSlateHistoryEntry>(); | |
NewEntry->EntryType = EGNInputSlateHistoryEntryType::InputProcessor; | |
NewEntry->EventType = InputEventType; | |
NewEntry->Info = bHandled ? TEXT("(Handled)") : TEXT(""); | |
NewEntry->bIsVerbose = !bHandled; | |
NewEntry->Spaces = ProcessInputCounter + RouteInputCounter; | |
InputHistoryEntries.Add(NewEntry); | |
} | |
} | |
void FGNInputEventDebugger::OnRouteInput(ESlateDebuggingInputEvent InputEventType, const FName& RoutedType) | |
{ | |
if (!bDebuggerInputEnabled && EnabledInputEvents[(uint8)InputEventType]) | |
{ | |
TSharedRef<FGNInputSlateHistoryEntry> NewEntry = MakeShared<FGNInputSlateHistoryEntry>(); | |
NewEntry->EntryType = EGNInputSlateHistoryEntryType::Route; | |
NewEntry->EventType = InputEventType; | |
NewEntry->Info = RoutedType.ToString(); | |
NewEntry->bIsVerbose = false; | |
NewEntry->Spaces = ProcessInputCounter + RouteInputCounter; | |
InputHistoryEntries.Add(NewEntry); | |
} | |
++RouteInputCounter; | |
} | |
void FGNInputEventDebugger::OnInputEvent(ESlateDebuggingInputEvent InputEventType, const FReply& InReply, const TSharedPtr<SWidget>& HandlerWidget) | |
{ | |
if (!bDebuggerInputEnabled && EnabledInputEvents[(uint8)InputEventType]) | |
{ | |
TSharedRef<FGNInputSlateHistoryEntry> NewEntry = MakeShared<FGNInputSlateHistoryEntry>(); | |
NewEntry->EntryType = EGNInputSlateHistoryEntryType::Event; | |
NewEntry->EventType = InputEventType; | |
NewEntry->bIsVerbose = !InReply.IsEventHandled(); | |
NewEntry->Spaces = ProcessInputCounter + RouteInputCounter; | |
FString AssetName, WidgetName; | |
UGNWidgetStatics::GetWidgetDebugInfo(HandlerWidget.Get(), AssetName, WidgetName); | |
NewEntry->Info += InReply.IsEventHandled() ? TEXT("(Handled) ") : TEXT(""); | |
NewEntry->Info += AssetName; | |
NewEntry->InfoVerbose = WidgetName; | |
InputHistoryEntries.Add(NewEntry); | |
} | |
} | |
void FGNInputEventDebugger::OnInputRouted(ESlateDebuggingInputEvent InputEventType) | |
{ | |
RouteInputCounter = FMath::Max(0, RouteInputCounter - 1); | |
} | |
void FGNInputEventDebugger::OnInputProcessed(ESlateDebuggingInputEvent InputEventType) | |
{ | |
ProcessInputCounter = FMath::Max(0, ProcessInputCounter - 1); | |
} | |
namespace InputSlateHistoryEntry | |
{ | |
using TString = TStringBuilder<64>; | |
void BuildSpaces(TStringBuilder<64>& Message, int32 Amount) | |
{ | |
const TCHAR* Space = TEXT(" "); | |
for (int32 SpaceCounter = 0; SpaceCounter < Amount; ++SpaceCounter) | |
{ | |
Message.Append(Space); | |
} | |
} | |
} | |
FString FGNInputSlateHistoryEntry::ToString(bool bVerbose) | |
{ | |
InputSlateHistoryEntry::TString Message; | |
InputSlateHistoryEntry::BuildSpaces(Message, Spaces); | |
switch (EntryType) | |
{ | |
case EGNInputSlateHistoryEntryType::Event: | |
Message.Append(TEXT("Event - ")); break; | |
case EGNInputSlateHistoryEntryType::Process: | |
Message.Append(TEXT("Process - ")); break; | |
case EGNInputSlateHistoryEntryType::InputProcessor: | |
Message.Append(TEXT("InputProcessor - ")); break; | |
case EGNInputSlateHistoryEntryType::Route: | |
Message.Append(TEXT("Route - ")); break; | |
} | |
Message.Append(Info); | |
if (bVerbose) | |
{ | |
Message.Append(TEXT(" - ")); | |
Message.Append(InfoVerbose); | |
} | |
return FString(Message); | |
} | |
#endif // WITH_GN_DEBUGGER && WITH_SLATE_DEBUGGING |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright Feral Cat Den, LLC. All Rights Reserved. | |
#pragma once | |
#if WITH_GN_DEBUGGER && WITH_SLATE_DEBUGGING | |
#include "CoreMinimal.h" | |
#include "Debugging/SlateDebugging.h" | |
#include "Input/Reply.h" | |
class SWidget; | |
enum class EGNInputSlateHistoryEntryType : uint8 | |
{ | |
Process, | |
InputProcessor, | |
Route, | |
Event | |
}; | |
enum class EGNInputSlateHistoryVerbosity : uint8 | |
{ | |
Normal, | |
Verbose, | |
VeryVerbose | |
}; | |
struct FGNInputSlateHistoryEntry | |
{ | |
EGNInputSlateHistoryEntryType EntryType; | |
ESlateDebuggingInputEvent EventType; | |
FString Info; | |
FString InfoVerbose; | |
uint8 bIsVerbose : 1; | |
uint8 Spaces = 0; | |
FString ToString(bool bVerbose); | |
}; | |
class FGNInputEventDebugger : public FSlateDebugging::IWidgetInputRoutingEvent | |
{ | |
public: | |
FGNInputEventDebugger(); | |
virtual ~FGNInputEventDebugger(); | |
void StartDebugging(); | |
void StopDebugging(); | |
TConstArrayView<TSharedRef<FGNInputSlateHistoryEntry>> GetHistoryEntriesView() const; | |
bool bEnabled; | |
bool bDebuggerInputEnabled; | |
int32 MaxInputHistoryEntries; | |
protected: | |
// IWidgetInputRoutingEvent implementation | |
virtual void OnProcessInput(ESlateDebuggingInputEvent InputEventType, const FInputEvent& Event) override; | |
virtual void OnPreProcessInput(ESlateDebuggingInputEvent InputEventType, const TCHAR* InputPrecessor, bool bHandled) override; | |
virtual void OnRouteInput(ESlateDebuggingInputEvent InputEventType, const FName& RoutedType) override; | |
virtual void OnInputEvent(ESlateDebuggingInputEvent InputEventType, const FReply& InReply, const TSharedPtr<SWidget>& HandlerWidget) override; | |
virtual void OnInputRouted(ESlateDebuggingInputEvent InputEventType) override; | |
virtual void OnInputProcessed(ESlateDebuggingInputEvent InputEventType) override; | |
TArray<TSharedRef<FGNInputSlateHistoryEntry>> InputHistoryEntries; | |
private: | |
int32 ProcessInputCounter; | |
int32 RouteInputCounter; | |
TBitArray<> EnabledInputEvents; | |
}; | |
#endif // WITH_GN_DEBUGGER && WITH_SLATE_DEBUGGING |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment