mirror of
				https://github.com/kevinporetti/UnrealImGui.git
				synced 2025-10-31 05:53:17 +00:00 
			
		
		
		
	Added debug code to ImGui Widget:
- Added ImGui.Debug.Widget console variable to enable/disable widget state debugging. - Added ImGui ImGui debug for widget state. - Added logging for widget state transitions.
This commit is contained in:
		
							parent
							
								
									f7816ee1fd
								
							
						
					
					
						commit
						f696393089
					
				| @ -12,6 +12,12 @@ | ||||
| #include "Utilities/ScopeGuards.h" | ||||
| 
 | ||||
| 
 | ||||
| DEFINE_LOG_CATEGORY_STATIC(LogImGuiWidget, Warning, All); | ||||
| 
 | ||||
| #define TEXT_INPUT_MODE(Val) ((Val) == EInputMode::MouseAndKeyboard ? TEXT("MouseAndKeyboard") : (Val) == EInputMode::MouseOnly ? TEXT("MouseOnly") : TEXT("None")) | ||||
| #define TEXT_BOOL(Val) ((Val) ? TEXT("true") : TEXT("false")) | ||||
| 
 | ||||
| 
 | ||||
| namespace CVars | ||||
| { | ||||
| 	TAutoConsoleVariable<int> InputEnabled(TEXT("ImGui.InputEnabled"), 0, | ||||
| @ -19,24 +25,44 @@ namespace CVars | ||||
| 		TEXT("0: disabled (default)\n") | ||||
| 		TEXT("1: enabled, input is routed to ImGui and with a few exceptions is consumed."), | ||||
| 		ECVF_Default); | ||||
| 
 | ||||
| 	TAutoConsoleVariable<int> DebugWidget(TEXT("ImGui.Debug.Widget"), 0, | ||||
| 		TEXT("Show debug for SImGuiWidget.\n") | ||||
| 		TEXT("0: disabled (default)\n") | ||||
| 		TEXT("1: enabled."), | ||||
| 		ECVF_Default); | ||||
| } | ||||
| 
 | ||||
| BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION | ||||
| void SImGuiWidget::Construct(const FArguments& InArgs) | ||||
| { | ||||
| 	checkf(InArgs._ModuleManager, TEXT("Null Module Manager argument")); | ||||
| 
 | ||||
| 	ModuleManager = InArgs._ModuleManager; | ||||
| 	ContextIndex = InArgs._ContextIndex; | ||||
| 
 | ||||
| 	ModuleManager->OnPostImGuiUpdate().AddRaw(this, &SImGuiWidget::OnPostImGuiUpdate); | ||||
| 
 | ||||
| 	// Sync visibility with default input enabled state.
 | ||||
| 	SetVisibilityFromInputEnabled(); | ||||
| 
 | ||||
| 	// Register to get post-update notifications, so we can clean frame updates.
 | ||||
| 	ModuleManager->OnPostImGuiUpdate().AddRaw(this, &SImGuiWidget::OnPostImGuiUpdate); | ||||
| 
 | ||||
| 	// Register self-debug function.
 | ||||
| 	auto* ContextProxy = ModuleManager->GetContextManager().GetContextProxy(ContextIndex); | ||||
| 	checkf(ContextProxy, TEXT("Missing context during widget construction: ContextIndex = %d"), ContextIndex); | ||||
| 	ContextProxy->OnDraw().AddRaw(this, &SImGuiWidget::OnDebugDraw); | ||||
| } | ||||
| END_SLATE_FUNCTION_BUILD_OPTIMIZATION | ||||
| 
 | ||||
| SImGuiWidget::~SImGuiWidget() | ||||
| { | ||||
| 	// Remove binding between this widget and its context proxy.
 | ||||
| 	if (auto* ContextProxy = ModuleManager->GetContextManager().GetContextProxy(ContextIndex)) | ||||
| 	{ | ||||
| 		ContextProxy->OnDraw().RemoveAll(this); | ||||
| 	} | ||||
| 
 | ||||
| 	// Unregister from post-update notifications.
 | ||||
| 	ModuleManager->OnPostImGuiUpdate().RemoveAll(this); | ||||
| } | ||||
| 
 | ||||
| @ -122,6 +148,8 @@ FReply SImGuiWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEv | ||||
| { | ||||
| 	Super::OnFocusReceived(MyGeometry, FocusEvent); | ||||
| 
 | ||||
| 	UE_LOG(LogImGuiWidget, VeryVerbose, TEXT("ImGui Widget %d - Focus Received."), ContextIndex); | ||||
| 
 | ||||
| 	// If widget has a keyboard focus we always maintain mouse input. Technically, if mouse is outside of the widget
 | ||||
| 	// area it won't generate events but we freeze its state until it either comes back or input is completely lost.
 | ||||
| 	UpdateInputMode(true, true); | ||||
| @ -133,6 +161,8 @@ void SImGuiWidget::OnFocusLost(const FFocusEvent& FocusEvent) | ||||
| { | ||||
| 	Super::OnFocusLost(FocusEvent); | ||||
| 
 | ||||
| 	UE_LOG(LogImGuiWidget, VeryVerbose, TEXT("ImGui Widget %d - Focus Lost."), ContextIndex); | ||||
| 
 | ||||
| 	UpdateInputMode(false, IsHovered()); | ||||
| } | ||||
| 
 | ||||
| @ -140,6 +170,8 @@ void SImGuiWidget::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent | ||||
| { | ||||
| 	Super::OnMouseEnter(MyGeometry, MouseEvent); | ||||
| 
 | ||||
| 	UE_LOG(LogImGuiWidget, VeryVerbose, TEXT("ImGui Widget %d - Mouse Enter."), ContextIndex); | ||||
| 
 | ||||
| 	// If mouse enters while input is active then we need to update mouse buttons because there is a chance that we
 | ||||
| 	// missed some events.
 | ||||
| 	if (InputMode != EInputMode::None) | ||||
| @ -157,6 +189,8 @@ void SImGuiWidget::OnMouseLeave(const FPointerEvent& MouseEvent) | ||||
| { | ||||
| 	Super::OnMouseLeave(MouseEvent); | ||||
| 
 | ||||
| 	UE_LOG(LogImGuiWidget, VeryVerbose, TEXT("ImGui Widget %d - Mouse Leave."), ContextIndex); | ||||
| 
 | ||||
| 	UpdateInputMode(HasKeyboardFocus(), false); | ||||
| } | ||||
| 
 | ||||
| @ -179,6 +213,9 @@ void SImGuiWidget::SetVisibilityFromInputEnabled() | ||||
| { | ||||
| 	// If we don't use input disable hit test to make this widget invisible for cursors hit detection.
 | ||||
| 	SetVisibility(bInputEnabled ? EVisibility::Visible : EVisibility::HitTestInvisible); | ||||
| 
 | ||||
| 	UE_LOG(LogImGuiWidget, VeryVerbose, TEXT("ImGui Widget %d - Visibility updated to '%s'."), | ||||
| 		ContextIndex, *GetVisibility().ToString()); | ||||
| } | ||||
| 
 | ||||
| void SImGuiWidget::UpdateInputEnabled() | ||||
| @ -188,6 +225,9 @@ void SImGuiWidget::UpdateInputEnabled() | ||||
| 	{ | ||||
| 		bInputEnabled = bEnabled; | ||||
| 
 | ||||
| 		UE_LOG(LogImGuiWidget, Log, TEXT("ImGui Widget %d - Input Enabled changed to '%s'."), | ||||
| 			ContextIndex, TEXT_BOOL(bInputEnabled)); | ||||
| 
 | ||||
| 		SetVisibilityFromInputEnabled(); | ||||
| 
 | ||||
| 		// Setup input to show cursor and take focus when we use input or clear state and pass focus back to viewport
 | ||||
| @ -219,6 +259,9 @@ void SImGuiWidget::UpdateInputMode(bool bNeedKeyboard, bool bNeedMouse) | ||||
| 
 | ||||
| 	if (InputMode != NewInputMode) | ||||
| 	{ | ||||
| 		UE_LOG(LogImGuiWidget, Verbose, TEXT("ImGui Widget %d - Input Mode changed from '%s' to '%s'."), | ||||
| 			ContextIndex, TEXT_INPUT_MODE(InputMode), TEXT_INPUT_MODE(NewInputMode)); | ||||
| 
 | ||||
| 		// We need to reset input components if we are either fully shutting down or we are downgrading from full to
 | ||||
| 		// mouse-only input mode.
 | ||||
| 		if (NewInputMode == EInputMode::None) | ||||
| @ -291,3 +334,64 @@ FVector2D SImGuiWidget::ComputeDesiredSize(float) const | ||||
| { | ||||
| 	return FVector2D{ 3840.f, 2160.f }; | ||||
| } | ||||
| 
 | ||||
| // Controls tweaked for 2-columns layout.
 | ||||
| namespace TwoColumns | ||||
| { | ||||
| 	static void Value(const char* Label, int Value) | ||||
| 	{ | ||||
| 		ImGui::Text("%s:", Label); ImGui::NextColumn(); | ||||
| 		ImGui::Text("%d", Value); ImGui::NextColumn(); | ||||
| 	} | ||||
| 
 | ||||
| 	static void Value(const char* Label, bool bValue) | ||||
| 	{ | ||||
| 		ImGui::Text("%s:", Label); ImGui::NextColumn(); | ||||
| 		ImGui::Text("%ls", TEXT_BOOL(bValue)); ImGui::NextColumn(); | ||||
| 	} | ||||
| 
 | ||||
| 	static void Value(const char* Label, const TCHAR* Value) | ||||
| 	{ | ||||
| 		ImGui::Text("%s:", Label); ImGui::NextColumn(); | ||||
| 		ImGui::Text("%ls", Value); ImGui::NextColumn(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void SImGuiWidget::OnDebugDraw() | ||||
| { | ||||
| 	bool bDebug = CVars::DebugWidget.GetValueOnGameThread() > 0; | ||||
| 	if (bDebug) | ||||
| 	{ | ||||
| 		ImGui::SetNextWindowSize(ImVec2(300, 200), ImGuiSetCond_Once); | ||||
| 		if (ImGui::Begin("ImGui Widget Debug", &bDebug)) | ||||
| 		{ | ||||
| 			ImGui::Columns(2, nullptr, false); | ||||
| 
 | ||||
| 			TwoColumns::Value("Context Index", ContextIndex); | ||||
| 
 | ||||
| 			ImGui::Separator(); | ||||
| 
 | ||||
| 			TwoColumns::Value("Input Enabled", bInputEnabled); | ||||
| 			TwoColumns::Value("Input Mode", TEXT_INPUT_MODE(InputMode)); | ||||
| 
 | ||||
| 			ImGui::Separator(); | ||||
| 
 | ||||
| 			TwoColumns::Value("Visibility", *GetVisibility().ToString()); | ||||
| 			TwoColumns::Value("Is Hovered", IsHovered()); | ||||
| 			TwoColumns::Value("Is Directly Hovered", IsDirectlyHovered()); | ||||
| 			TwoColumns::Value("Has Keyboard Input", HasKeyboardFocus()); | ||||
| 
 | ||||
| 			ImGui::Columns(1); | ||||
| 		} | ||||
| 		ImGui::End(); | ||||
| 
 | ||||
| 		if (!bDebug) | ||||
| 		{ | ||||
| 			CVars::DebugWidget->ClearFlags(ECVF_SetByConsole); | ||||
| 			CVars::DebugWidget->Set(0); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #undef TEXT_INPUT_MODE | ||||
| #undef TEXT_BOOL | ||||
|  | ||||
| @ -91,6 +91,8 @@ private: | ||||
| 
 | ||||
| 	virtual FVector2D ComputeDesiredSize(float) const override; | ||||
| 
 | ||||
| 	void OnDebugDraw(); | ||||
| 
 | ||||
| 	FImGuiModuleManager* ModuleManager = nullptr; | ||||
| 
 | ||||
| 	mutable TArray<FSlateVertex> VertexBuffer; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Sebastian
						Sebastian