CogWindow: Change the way Cog shortcuts are treated

Shortcuts to enable imgui (F1), enable actor selection (F5), loading and saving layouts, used to be handled by registering console commands with shortcuts. Now console commands can still be executed, but the shortcuts are handled by directly checking if the corresponding key is pressed from the UPlayerInput when imgui do not need Text input.
This should fix cases where the console shortcuts were not executed (typically with CommonUI menus)
This commit is contained in:
Arnaud Jamin
2025-01-24 01:19:18 -05:00
parent 980fe16f6e
commit 4f8d969ce5
11 changed files with 365 additions and 176 deletions
@@ -50,17 +50,11 @@ void FCogEngineWindow_CommandBindings::RenderContent()
ImGui::SameLine();
if (FCogWindowWidgets::ButtonWithTooltip(
"Register Default Commands",
"Register the default commands used to control Cog:\n\n"
"[Tab] Cog.ToggleInput\n"
"[F1] Cog.LoadLayout 1\n"
"[F2] Cog.LoadLayout 2\n"
"[F3] Cog.LoadLayout 3\n"
"[F4] Cog.LoadLayout 4\n"
"[F5] Cog.ToggleSelectionMode\n"
"Disable Conflicting Commands",
"Disable the existing Unreal command shortcuts mapped to same shortcuts Cog is using. Typically, if the F1 shortcut is used to toggle Inputs, the Unreal wireframe command will get disabled."
))
{
GetOwner()->RegisterDefaultCommandBindings();
GetOwner()->DisableConflictingCommands();
}
for (FKeyBind& KeyBind : PlayerInput->DebugExecBindings)
@@ -79,7 +73,6 @@ void FCogEngineWindow_CommandBindings::RenderContent()
PlayerInput->SaveConfig();
}
ImGui::PopID();
Index++;
}
@@ -9,6 +9,7 @@
#include "CogWindowConsoleCommandManager.h"
#include "CogWindowManager.h"
#include "CogWindowWidgets.h"
#include "CogWindow_Settings.h"
#include "Components/PrimitiveComponent.h"
#include "EngineUtils.h"
#include "GameFramework/Character.h"
@@ -35,7 +36,7 @@ void FCogEngineWindow_Selection::Initialize()
GetWorld(),
FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
ToggleSelectionMode();
GetOwner()->SetActivateSelectionMode(!GetOwner()->GetActivateSelectionMode());
}));
TryReapplySelection();
@@ -122,49 +123,11 @@ TSubclassOf<AActor> FCogEngineWindow_Selection::GetSelectedActorClass() const
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Selection::ToggleSelectionMode()
{
if (bSelectionModeActive)
{
DeactivateSelectionMode();
}
else
{
ActivateSelectionMode();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Selection::ActivateSelectionMode()
{
bSelectionModeActive = true;
bIsInputEnabledBeforeEnteringSelectionMode = GetOwner()->GetContext().GetEnableInput();
GetOwner()->GetContext().SetEnableInput(true);
GetOwner()->SetActivateSelectionMode(true);
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Selection::HackWaitInputRelease()
{
WaitInputReleased = 1;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Selection::DeactivateSelectionMode()
{
bSelectionModeActive = false;
//--------------------------------------------------------------------------------------------
// We can enter selection mode by a command, and ImGui might not have the input focus
// When in selection mode we need ImGui to have the input focus
// When leaving selection mode we want to leave it as it was before
//--------------------------------------------------------------------------------------------
GetOwner()->GetContext().SetEnableInput(bIsInputEnabledBeforeEnteringSelectionMode);
GetOwner()->SetActivateSelectionMode(false);
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Selection::RenderTick(float DeltaTime)
{
@@ -175,7 +138,7 @@ void FCogEngineWindow_Selection::RenderTick(float DeltaTime)
SetGlobalSelection(GetLocalPlayerPawn());
}
if (bSelectionModeActive)
if (GetOwner()->GetActivateSelectionMode())
{
TickSelectionMode();
}
@@ -198,7 +161,7 @@ void FCogEngineWindow_Selection::RenderContent()
{
if (ImGui::MenuItem("Pick"))
{
ActivateSelectionMode();
GetOwner()->SetActivateSelectionMode(true);
//HackWaitInputRelease();
}
@@ -242,14 +205,14 @@ void FCogEngineWindow_Selection::TickSelectionMode()
{
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right))
{
DeactivateSelectionMode();
GetOwner()->SetActivateSelectionMode(false);
return;
}
APlayerController* PlayerController = GetLocalPlayerController();
if (PlayerController == nullptr)
{
DeactivateSelectionMode();
GetOwner()->SetActivateSelectionMode(false);
return;
}
@@ -309,7 +272,7 @@ void FCogEngineWindow_Selection::TickSelectionMode()
FCogWindowWidgets::ActorFrame(*HoveredActor);
}
if (bSelectionModeActive)
if (GetOwner()->GetActivateSelectionMode())
{
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
@@ -320,7 +283,7 @@ void FCogEngineWindow_Selection::TickSelectionMode()
SetGlobalSelection(HoveredActor);
}
DeactivateSelectionMode();
GetOwner()->SetActivateSelectionMode(false);
}
else
{
@@ -357,7 +320,7 @@ void FCogEngineWindow_Selection::RenderMainMenuWidget(int32 SubWidgetIndex, floa
if (ImGui::Button("Pick", ImVec2(Width, 0)))
{
ActivateSelectionMode();
GetOwner()->SetActivateSelectionMode(true);
HackWaitInputRelease();
}
RenderPickButtonTooltip();
@@ -422,7 +385,7 @@ void FCogEngineWindow_Selection::RenderPickButtonTooltip()
{
if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary))
{
const FString Shortcut = FCogImguiInputHelper::CommandToString(*GetWorld(), ToggleSelectionModeCommand);
const FString Shortcut = FCogImguiInputHelper::KeyInfoToString(GetOwner()->GetSettings()->ToggleSelectionShortcut);
ImGui::SetTooltip("Enter picking mode to pick an actor on screen. %s", TCHAR_TO_ANSI(*Shortcut));
}
}
@@ -23,8 +23,6 @@ public:
virtual void Shutdown() override;
bool GetIsSelecting() const { return bSelectionModeActive; }
const TArray<TSubclassOf<AActor>>& GetActorClasses() const { return ActorClasses; }
void SetActorClasses(const TArray<TSubclassOf<AActor>>& Value) { ActorClasses = Value; }
@@ -33,12 +31,6 @@ public:
void SetTraceType(ETraceTypeQuery Value) { TraceType = Value; }
virtual void ActivateSelectionMode();
virtual void DeactivateSelectionMode();
virtual void ToggleSelectionMode();
protected:
virtual void TryReapplySelection() const;
@@ -73,8 +65,6 @@ protected:
FVector LastSelectedActorLocation = FVector::ZeroVector;
bool bSelectionModeActive = false;
bool bIsInputEnabledBeforeEnteringSelectionMode = false;
int32 WaitInputReleased = 0;
@@ -95,6 +95,18 @@ bool FCogImguiInputHelper::IsCheckBoxStateMatchingValue(ECheckBoxState CheckBoxS
const bool Result = (CheckBoxState == ECheckBoxState::Undetermined) || ((CheckBoxState == ECheckBoxState::Checked) == bValue);
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsCheckBoxStateMatchingKeybindModifier(ECheckBoxState InCheckBoxState, bool InRequireModifier, bool InIgnoreModifier)
{
switch (InCheckBoxState)
{
case ECheckBoxState::Undetermined: return true;
case ECheckBoxState::Checked: return InRequireModifier && InIgnoreModifier == false;
case ECheckBoxState::Unchecked: return InRequireModifier == false && InIgnoreModifier;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyEventMatchingKeyInfo(const FKeyEvent& KeyEvent, const FCogImGuiKeyInfo& KeyInfo)
@@ -166,6 +178,18 @@ void FCogImguiInputHelper::KeyInfoToKeyBind(const FCogImGuiKeyInfo& KeyInfo, FKe
BREAK_CHECKBOX_STATE(KeyInfo.Cmd, KeyBind.Cmd, KeyBind.bIgnoreCmd);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyBindMatchingKeyInfo(const FKeyBind& InKeyBind, const FCogImGuiKeyInfo& InKeyInfo)
{
const bool Result = (InKeyInfo.Key == InKeyBind.Key)
&& IsCheckBoxStateMatchingKeybindModifier(InKeyInfo.Shift, InKeyBind.Shift, InKeyBind.bIgnoreShift)
&& IsCheckBoxStateMatchingKeybindModifier(InKeyInfo.Ctrl, InKeyBind.Control, InKeyBind.bIgnoreCtrl)
&& IsCheckBoxStateMatchingKeybindModifier(InKeyInfo.Alt, InKeyBind.Alt, InKeyBind.bIgnoreAlt)
&& IsCheckBoxStateMatchingKeybindModifier(InKeyInfo.Cmd, InKeyBind.Cmd, InKeyBind.bIgnoreCmd);
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::WasKeyInfoJustPressed(APlayerController& PlayerController, const FCogImGuiKeyInfo& KeyInfo)
{
@@ -304,32 +328,67 @@ FString FCogImguiInputHelper::CommandToString(const UPlayerInput* PlayerInput, c
//--------------------------------------------------------------------------------------------------------------------------
FString FCogImguiInputHelper::KeyBindToString(const FKeyBind& KeyBind)
{
FString Result;
FString Result = "[";
if (KeyBind.Alt)
{
Result = Result.Append("Alt ");
Result += FString("Alt ");
}
if (KeyBind.Shift)
{
Result = Result.Append("Shift ");
Result += FString("Shift ");
}
if (KeyBind.Control)
{
Result = Result.Append("Ctrl ");
Result += FString("Ctrl ");
}
if (KeyBind.Cmd)
{
Result = Result.Append("Cmd ");
Result += FString("Cmd ");
}
Result = Result.Printf(TEXT("[%s]"), *KeyBind.Key.ToString());
Result += KeyBind.Key.ToString();
Result += FString("]");
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
FString FCogImguiInputHelper::KeyInfoToString(const FCogImGuiKeyInfo& InKeyInfo)
{
if (InKeyInfo == FKey())
{
return FString("");
}
FString Result = "[";
if (InKeyInfo.Alt == ECheckBoxState::Checked)
{
Result += FString("Alt ");
}
if (InKeyInfo.Shift == ECheckBoxState::Checked)
{
Result += FString("Shift ");
}
if (InKeyInfo.Ctrl == ECheckBoxState::Checked)
{
Result += FString("Ctrl ");
}
if (InKeyInfo.Cmd == ECheckBoxState::Checked)
{
Result += FString("Cmd ");
}
Result += InKeyInfo.Key.ToString();
Result += FString("]");
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent, const FKeyBind& KeyBind)
@@ -364,6 +423,22 @@ bool FCogImguiInputHelper::IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent,
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyInfoPressed(const UPlayerInput* PlayerInput, const FCogImGuiKeyInfo& InKeyInfo)
{
const bool bKeyPressed = PlayerInput->WasJustPressed(InKeyInfo.Key);
if (bKeyPressed == false)
{ return false; }
if (IsCheckBoxStateMatchingValue(InKeyInfo.Ctrl, PlayerInput->IsCtrlPressed())
&& IsCheckBoxStateMatchingValue(InKeyInfo.Shift, PlayerInput->IsShiftPressed())
&& IsCheckBoxStateMatchingValue(InKeyInfo.Alt, PlayerInput->IsAltPressed())
&& IsCheckBoxStateMatchingValue(InKeyInfo.Cmd, PlayerInput->IsCmdPressed()))
{ return true; }
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogImguiInputHelper::IsKeyBoundToCommand(const UPlayerInput* InPlayerInput, const FKeyEvent& KeyEvent)
{
@@ -28,10 +28,16 @@ public:
static bool IsCheckBoxStateMatchingValue(ECheckBoxState CheckBoxState, bool bValue);
static bool IsCheckBoxStateMatchingKeybindModifier(ECheckBoxState InCheckBoxState, bool InRequireModifier, bool InIgnoreModifier);
static bool IsKeyEventMatchingKeyInfo(const FKeyEvent& KeyEvent, const FCogImGuiKeyInfo& InputChord);
static bool IsKeyBindMatchingKeyInfo(const FKeyBind& InKeyBind, const FCogImGuiKeyInfo& InKeyInfo);
static bool IsKeyEventMatchingKeyBind(const FKeyEvent& KeyEvent, const FKeyBind& KeyBind);
static bool IsKeyInfoPressed(const UPlayerInput* PlayerInput, const FCogImGuiKeyInfo& InKeyInfo);
static ECheckBoxState MakeCheckBoxState(uint8 RequireValue, uint8 IgnoreValue);
static void KeyBindToKeyInfo(const FKeyBind& KeyBind, FCogImGuiKeyInfo& KeyInfo);
@@ -56,6 +62,8 @@ public:
static FString KeyBindToString(const FKeyBind& KeyBind);
static FString KeyInfoToString(const FCogImGuiKeyInfo& InKeyInfo);
static bool IsMouseInsideMainViewport();
static bool IsKeyBoundToCommand(const UPlayerInput* InPlayerInput, const FKeyEvent& KeyEvent);
@@ -27,28 +27,6 @@ UCogWindowManager::UCogWindowManager()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::PostInitProperties()
{
Super::PostInitProperties();
//if (bRegisterDefaultCommands)
//{
// if (RegisterDefaultCommandBindings())
// {
// bRegisterDefaultCommands = false;
// }
//}
//-------------------------------------------------------------------------------
// Currently always register default commands.
// Since UE5.4, the ini files must have this to be saved:
// [SectionsToSave]
// bCanSaveAllSections = True
//-------------------------------------------------------------------------------
RegisterDefaultCommandBindings();
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::InitializeInternal()
{
@@ -72,6 +50,12 @@ void UCogWindowManager::InitializeInternal()
SpaceWindows.Add(AddWindow<FCogWindow_Spacing>("Spacing 3", false));
SpaceWindows.Add(AddWindow<FCogWindow_Spacing>("Spacing 4", false));
Settings = GetConfig<UCogWindowConfig_Settings>();
if (Settings->bResolveShortcutsConflicts)
{
DisableConflictingCommands();
}
LayoutsWindow = AddWindow<FCogWindow_Layouts>("Window.Layouts", false);
SettingsWindow = AddWindow<FCogWindow_Settings>("Window.Settings", false);
@@ -182,7 +166,7 @@ void UCogWindowManager::Tick(float DeltaTime)
{
return;
}
if (IsInitialized == false)
{
InitializeInternal();
@@ -205,6 +189,7 @@ void UCogWindowManager::Tick(float DeltaTime)
if (Context.BeginFrame(DeltaTime))
{
HandleInputs();
Render(DeltaTime);
Context.EndFrame();
}
@@ -214,13 +199,12 @@ void UCogWindowManager::Tick(float DeltaTime)
void UCogWindowManager::Render(float DeltaTime)
{
FCogImGuiContextScope ImGuiContextScope(Context);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode | ImGuiDockNodeFlags_AutoHideTabBar);
ImGui::PopStyleColor(1);
const bool bCompactSaved = SettingsWindow->GetSettingsConfig()->bCompactMode;
const bool bCompactSaved = Settings->bCompactMode;
if (bCompactSaved)
{
FCogWindowWidgets::PushStyleCompact();
@@ -246,7 +230,7 @@ void UCogWindowManager::Render(float DeltaTime)
if (Window->GetIsVisible() && bIsSelectionModeActive == false)
{
if (SettingsWindow->GetSettingsConfig()->bTransparentMode)
if (Settings->bTransparentMode)
{
ImGui::SetNextWindowBgAlpha(0.35f);
}
@@ -268,8 +252,8 @@ void UCogWindowManager::AddWindow(FCogWindow* Window, const FString& Name, const
{
Window->SetFullName(Name);
Window->SetOwner(this);
Window->Initialize();
Windows.Add(Window);
Window->Initialize();
if (Window->HasWidget())
{
@@ -299,18 +283,6 @@ FCogWindow* UCogWindowManager::FindWindowByID(const ImGuiID ID)
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::SetActivateSelectionMode(const bool Value)
{
SelectionModeActiveCounter = FMath::Max(SelectionModeActiveCounter + (Value ? 1 : -1), 0);
bIsSelectionModeActive = SelectionModeActiveCounter > 0;
if (bIsSelectionModeActive)
{
Context.SetEnableInput(true);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::ResetLayout()
{
@@ -414,9 +386,7 @@ void UCogWindowManager::RenderMainMenu()
{
CloseAllWindows();
}
ImGui::Separator();
RenderMenuItem(*LayoutsWindow, "Layouts");
@@ -570,7 +540,7 @@ void UCogWindowManager::RenderOptionMenu(FMenu& Menu)
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::RenderMenuItem(FCogWindow& Window, const char* MenuItemName)
{
if (SettingsWindow->GetSettingsConfig()->bShowWindowsInMainMenu)
if (Settings->bShowWindowsInMainMenu)
{
ImGui::SetNextWindowSizeConstraints(
ImVec2(FCogWindowWidgets::GetFontWidth() * 40, ImGui::GetTextLineHeightWithSpacing() * 5),
@@ -604,7 +574,7 @@ void UCogWindowManager::RenderMenuItem(FCogWindow& Window, const char* MenuItemN
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::RenderMenuItemHelp(FCogWindow& Window)
{
if (SettingsWindow->GetSettingsConfig()->bShowHelp)
if (Settings->bShowHelp)
{
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - FCogWindowWidgets::GetFontWidth() * 3.0f);
@@ -760,31 +730,6 @@ void UCogWindowManager::ResetAllWindowsConfig()
}
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogWindowManager::RegisterDefaultCommandBindings()
{
if (GetWorld() == nullptr)
{
return false;
}
UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld());
if (PlayerInput == nullptr)
{
return false;
}
AddCommand(PlayerInput, "Cog.ToggleInput", EKeys::F1);
AddCommand(PlayerInput, "Cog.LoadLayout 1", EKeys::F2);
AddCommand(PlayerInput, "Cog.LoadLayout 2", EKeys::F3);
AddCommand(PlayerInput, "Cog.LoadLayout 3", EKeys::F4);
AddCommand(PlayerInput, "Cog.ToggleSelectionMode", EKeys::F5);
SortCommands(PlayerInput);
PlayerInput->SaveConfig();
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::AddCommand(UPlayerInput* PlayerInput, const FString& Command, const FKey& Key)
{
@@ -890,3 +835,95 @@ void UCogWindowManager::DisableInputMode()
UE_LOG(LogCogImGui, Verbose, TEXT("UCogWindowManager::DisableInputMode"));
Context.SetEnableInput(false);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::HandleInputs()
{
const UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld());
if (PlayerInput == nullptr)
{ return; }
if (ImGui::GetIO().WantTextInput)
{ return; }
if (FCogImguiInputHelper::IsKeyInfoPressed(PlayerInput, Settings->ToggleImguiInputShortcut))
{
ToggleInputMode();
}
else if (FCogImguiInputHelper::IsKeyInfoPressed(PlayerInput, Settings->ToggleSelectionShortcut))
{
SetActivateSelectionMode(!GetActivateSelectionMode());
}
for (int i = 0; i < Settings->LoadLayoutShortcuts.Num(); ++i)
{
if (FCogImguiInputHelper::IsKeyInfoPressed(PlayerInput, Settings->LoadLayoutShortcuts[i]))
{
LoadLayout(i);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::SetActivateSelectionMode(const bool Value)
{
SelectionModeActiveCounter = FMath::Max(SelectionModeActiveCounter + (Value ? 1 : -1), 0);
bIsSelectionModeActive = SelectionModeActiveCounter > 0;
if (bIsSelectionModeActive)
{
bIsInputEnabledBeforeEnteringSelectionMode = GetContext().GetEnableInput();
Context.SetEnableInput(true);
}
else
{
GetContext().SetEnableInput(bIsInputEnabledBeforeEnteringSelectionMode);
}
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogWindowManager::GetActivateSelectionMode() const
{
return SelectionModeActiveCounter > 0;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::DisableConflictingCommands() const
{
if (GetWorld() == nullptr)
{ return; }
UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld());
if (PlayerInput == nullptr)
{ return; }
DisableConflictingCommand(PlayerInput, Settings->ToggleImguiInputShortcut);
DisableConflictingCommand(PlayerInput, Settings->ToggleSelectionShortcut);
for (int32 i = 0; i < Settings->LoadLayoutShortcuts.Num(); ++i)
{
DisableConflictingCommand(PlayerInput, Settings->LoadLayoutShortcuts[i]);
}
for (int32 i = 0; i < Settings->SaveLayoutShortcuts.Num(); ++i)
{
DisableConflictingCommand(PlayerInput, Settings->SaveLayoutShortcuts[i]);
}
PlayerInput->SaveConfig();
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::DisableConflictingCommand(UPlayerInput* InPlayerInput, const FCogImGuiKeyInfo& InShortcut)
{
if (InPlayerInput == nullptr)
{ return; }
for (FKeyBind& KeyBind :InPlayerInput->DebugExecBindings)
{
if (FCogImguiInputHelper::IsKeyBindMatchingKeyInfo(KeyBind, InShortcut))
{
KeyBind.bDisabled = true;
}
}
}
@@ -459,8 +459,12 @@ bool FCogWindowWidgets::InputKey(const char* Label, FCogImGuiKeyInfo& KeyInfo)
ImGui::PushID(Label);
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted(Label);
ImGui::BeginDisabled();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 10);
ImGui::InputText("##Shortcut", const_cast<char*>(Label), IM_ARRAYSIZE(Label));
ImGui::EndDisabled();
ImGui::SameLine();
const bool HasChanged = InputKey(KeyInfo);
ImGui::PopID();
@@ -471,17 +475,28 @@ bool FCogWindowWidgets::InputKey(const char* Label, FCogImGuiKeyInfo& KeyInfo)
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::InputKey(FCogImGuiKeyInfo& KeyInfo)
{
static TArray<FKey> AllKeys;
if (AllKeys.IsEmpty())
{
EKeys::GetAllKeys(AllKeys);
}
bool HasKeyChanged = false;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 6);
if (ImGui::BeginCombo("##Key", TCHAR_TO_ANSI(*KeyInfo.Key.ToString()), ImGuiComboFlags_HeightLarge))
{
{
bool IsSelected = KeyInfo.Key == FKey();
if (ImGui::Selectable("None", IsSelected))
{
KeyInfo.Key = FKey();
HasKeyChanged = true;
}
}
ImGui::Separator();
static TArray<FKey> AllKeys;
if (AllKeys.IsEmpty())
{
EKeys::GetAllKeys(AllKeys);
}
for (int32 i = 0; i < AllKeys.Num(); ++i)
{
const FKey Key = AllKeys[i];
@@ -523,6 +538,27 @@ bool FCogWindowWidgets::KeyBind(FKeyBind& KeyBind)
const auto Str = StringCast<ANSICHAR>(*KeyBind.Command);
ImStrncpy(Buffer, Str.Get(), IM_ARRAYSIZE(Buffer));
bool Disable = !KeyBind.bDisabled;
if (ImGui::Checkbox("##Disable", &Disable))
{
KeyBind.bDisabled = !Disable;
}
if (KeyBind.bDisabled)
{
ImGui::SetItemTooltip("Enable command");
}
else
{
ImGui::SetItemTooltip("Disable command");
}
if (KeyBind.bDisabled)
{
ImGui::BeginDisabled();
}
ImGui::SameLine();
bool HasChanged = false;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
if (ImGui::InputText("##Command", Buffer, IM_ARRAYSIZE(Buffer)))
@@ -533,7 +569,7 @@ bool FCogWindowWidgets::KeyBind(FKeyBind& KeyBind)
FCogImGuiKeyInfo KeyInfo;
FCogImguiInputHelper::KeyBindToKeyInfo(KeyBind, KeyInfo);
ImGui::SameLine();
if (InputKey(KeyInfo))
{
@@ -541,6 +577,11 @@ bool FCogWindowWidgets::KeyBind(FKeyBind& KeyBind)
FCogImguiInputHelper::KeyInfoToKeyBind(KeyInfo, KeyBind);
}
if (KeyBind.bDisabled)
{
ImGui::EndDisabled();
}
return HasChanged;
}
@@ -2,6 +2,7 @@
#include "CogImguiInputHelper.h"
#include "CogWindowManager.h"
#include "CogWindow_Settings.h"
#include "InputCoreTypes.h"
//--------------------------------------------------------------------------------------------------------------------------
@@ -27,13 +28,13 @@ void FCogWindow_Layouts::RenderContent()
}
ImGui::Separator();
for (int32 i = 1; i <= 4; ++i)
for (int32 i = 0; i < 4; ++i)
{
RenderLoadLayoutMenuItem(PlayerInput, i);
}
ImGui::Separator();
for (int32 i = 1; i <= 4; ++i)
for (int32 i = 0; i < 4; ++i)
{
RenderSaveLayoutMenuItem(PlayerInput, i);
}
@@ -43,21 +44,29 @@ void FCogWindow_Layouts::RenderContent()
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindow_Layouts::RenderLoadLayoutMenuItem(const UPlayerInput* PlayerInput, int LayoutIndex)
{
const FString Command = FString::Printf(TEXT("%s %d"), *UCogWindowManager::LoadLayoutCommand, LayoutIndex);
const FString Shortcut = FCogImguiInputHelper::CommandToString(PlayerInput, Command);
if (ImGui::MenuItem(TCHAR_TO_ANSI(*FString::Printf(TEXT("Load Layout %d"), LayoutIndex)), TCHAR_TO_ANSI(*Shortcut)))
FString Shortcut;
if (GetOwner()->GetSettings()->LoadLayoutShortcuts.IsValidIndex(LayoutIndex))
{
GetOwner()->LoadLayout(LayoutIndex);
Shortcut = FCogImguiInputHelper::KeyInfoToString(GetOwner()->GetSettings()->LoadLayoutShortcuts[LayoutIndex]);
}
if (ImGui::MenuItem(TCHAR_TO_ANSI(*FString::Printf(TEXT("Load Layout %d"), LayoutIndex + 1)), TCHAR_TO_ANSI(*Shortcut)))
{
GetOwner()->LoadLayout(LayoutIndex + 1);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindow_Layouts::RenderSaveLayoutMenuItem(const UPlayerInput* PlayerInput, int LayoutIndex)
{
const FString Command = FString::Printf(TEXT("%s %d"), *UCogWindowManager::SaveLayoutCommand, LayoutIndex);
const FString Shortcut = FCogImguiInputHelper::CommandToString(PlayerInput, Command);
if (ImGui::MenuItem(TCHAR_TO_ANSI(*FString::Printf(TEXT("Save Layout %d"), LayoutIndex)), TCHAR_TO_ANSI(*Shortcut)))
FString Shortcut;
if (GetOwner()->GetSettings()->LoadLayoutShortcuts.IsValidIndex(LayoutIndex))
{
GetOwner()->SaveLayout(LayoutIndex);
Shortcut = FCogImguiInputHelper::KeyInfoToString(GetOwner()->GetSettings()->SaveLayoutShortcuts[LayoutIndex]);
}
if (ImGui::MenuItem(TCHAR_TO_ANSI(*FString::Printf(TEXT("Save Layout %d"), LayoutIndex + 1)), TCHAR_TO_ANSI(*Shortcut)))
{
GetOwner()->SaveLayout(LayoutIndex + 1);
}
}
@@ -5,7 +5,7 @@
#include "CogWindowManager.h"
#include "CogWindowWidgets.h"
#include "imgui.h"
#include "imgui.h"
#include "imgui_internal.h"
#include "InputCoreTypes.h"
//--------------------------------------------------------------------------------------------------------------------------
@@ -78,7 +78,7 @@ void FCogWindow_Settings::RenderContent()
Context.SetEnableInput(bEnableInput);
}
ImGui::SetItemTooltip("Enable ImGui inputs. When enabled the ImGui menu is shown and inputs are forwarded to ImGui.");
FCogWindowWidgets::MenuItemShortcut("EnableInputShortcut", FCogImguiInputHelper::CommandToString(PlayerInput, UCogWindowManager::ToggleInputCommand));
FCogWindowWidgets::MenuItemShortcut("EnableInputShortcut", FCogImguiInputHelper::KeyInfoToString(Config->ToggleImguiInputShortcut));
//-------------------------------------------------------------------------------------------
bool bShareKeyboard = Context.GetShareKeyboard();
@@ -121,12 +121,16 @@ void FCogWindow_Settings::RenderContent()
//-------------------------------------------------------------------------------------------
ImGui::CheckboxFlags("Keyboard Navigation", &IO.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
ImGui::SetItemTooltip("Use the keyboard to navigate in ImGui windows with the following keys : Tab, Directional Arrows, Space, Enter.");
//-------------------------------------------------------------------------------------------
//ImGui::CheckboxFlags("Gamepad Navigation", &IO.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
//ImGui::SetItemTooltip("Use the gamepad to navigate in ImGui windows.");
//-------------------------------------------------------------------------------------------
ImGui::Checkbox("Disable Conflicting Commands", &Config->bResolveShortcutsConflicts);
ImGui::SetItemTooltip("Disable the existing Unreal command shortcuts mapped to same shortcuts Cog is using. Typically, if the F1 shortcut is used to toggle Inputs, the Unreal wireframe command will get disabled.");
}
//-------------------------------------------------------------------------------------------
//ImGui::CheckboxFlags("Gamepad Navigation", &IO.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
//ImGui::SetItemTooltip("Use the gamepad to navigate in ImGui windows.");
//-------------------------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Window", ImGuiTreeNodeFlags_DefaultOpen))
{
@@ -163,6 +167,30 @@ void FCogWindow_Settings::RenderContent()
}
}
//-------------------------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Shortcuts", ImGuiTreeNodeFlags_DefaultOpen))
{
RenderShortcut("Toggle ImGui Input", Config->ToggleImguiInputShortcut);
RenderShortcut("Toggle Selection", Config->ToggleSelectionShortcut);
ImGui::Separator();
char Buffer[32];
for (int32 i = 0; i < Config->LoadLayoutShortcuts.Num(); ++i)
{
ImFormatString(Buffer, IM_ARRAYSIZE(Buffer), "Load Layout %d", i + 1);
RenderShortcut(Buffer, Config->LoadLayoutShortcuts[i]);
}
ImGui::Separator();
for (int32 i = 0; i < Config->SaveLayoutShortcuts.Num(); ++i)
{
ImFormatString(Buffer, IM_ARRAYSIZE(Buffer), "Save Layout %d", i + 1);
RenderShortcut(Buffer, Config->SaveLayoutShortcuts[i]);
}
}
//-------------------------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Config"))
{
@@ -198,3 +226,15 @@ void FCogWindow_Settings::SetDPIScale(float Value) const
Config->DPIScale = Value;
GetOwner()->GetContext().SetDPIScale(Config->DPIScale);
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindow_Settings::RenderShortcut(const char* Label, FCogImGuiKeyInfo& KeyInfo)
{
if (FCogWindowWidgets::InputKey(Label, KeyInfo))
{
if (Config->bResolveShortcutsConflicts)
{
GetOwner()->DisableConflictingCommands();
}
}
}
@@ -2,6 +2,7 @@
#include "CoreMinimal.h"
#include "CogImguiContext.h"
#include "CogWindow_Settings.h"
#include "imgui.h"
#include "CogWindowManager.generated.h"
@@ -26,8 +27,6 @@ public:
UCogWindowManager();
virtual void PostInitProperties() override;
virtual void Shutdown();
virtual void SortMainMenu();
@@ -56,11 +55,11 @@ public:
virtual void SetActivateSelectionMode(bool Value);
virtual bool GetActivateSelectionMode() const;
virtual void ResetAllWindowsConfig();
virtual bool RegisterDefaultCommandBindings();
const FCogWindow_Settings* GetSettingsWindow() const { return SettingsWindow; }
const UCogWindowConfig_Settings* GetSettings() const { return Settings.Get(); }
UCogCommonConfig* GetConfig(const TSubclassOf<UCogCommonConfig> ConfigClass);
@@ -80,6 +79,8 @@ public:
static void SortCommands(UPlayerInput* PlayerInput);
void DisableConflictingCommands() const;
protected:
friend class FCogWindow_Layouts;
@@ -107,6 +108,8 @@ protected:
virtual void ToggleInputMode();
virtual void DisableInputMode();
virtual void HandleInputs();
static void SettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*);
@@ -118,6 +121,8 @@ protected:
static void SettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
static void DisableConflictingCommand(UPlayerInput* InPlayerInput, const FCogImGuiKeyInfo& InShortcut);
static FString ToggleInputCommand;
static FString DisableInputCommand;
@@ -135,8 +140,8 @@ protected:
mutable TArray<const UObject*> Assets;
UPROPERTY(Config)
bool bRegisterDefaultCommands = true;
bool bShowMainMenu = false;
FCogImguiContext Context;
TArray<FCogWindow*> Windows;
@@ -148,6 +153,8 @@ protected:
TArray<FCogWindow*> SpaceWindows;
FCogWindow_Settings* SettingsWindow = nullptr;
TWeakObjectPtr<UCogWindowConfig_Settings> Settings;
FCogWindow_Layouts* LayoutsWindow = nullptr;
@@ -156,6 +163,8 @@ protected:
int32 LayoutToLoad = -1;
int32 SelectionModeActiveCounter = 0;
bool bIsInputEnabledBeforeEnteringSelectionMode = false;
bool bIsSelectionModeActive = false;
@@ -176,7 +185,7 @@ template<class T>
T* UCogWindowManager::GetConfig()
{
static_assert(TPointerIsConvertibleFromTo<T, const UCogCommonConfig>::Value);
return Cast<T>(&GetConfig(T::StaticClass()));
return Cast<T>(GetConfig(T::StaticClass()));
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -2,7 +2,9 @@
#include "CoreMinimal.h"
#include "CogCommonConfig.h"
#include "CogImguiKeyInfo.h"
#include "CogWindow.h"
#include "GameFramework/PlayerInput.h"
#include "CogWindow_Settings.generated.h"
class UCogEngineConfig_Settings;
@@ -30,6 +32,8 @@ protected:
virtual void ResetConfig() override;
virtual void RenderShortcut(const char* Label, FCogImGuiKeyInfo& KeyInfo);
TObjectPtr<UCogWindowConfig_Settings> Config = nullptr;
};
@@ -75,6 +79,21 @@ public:
UPROPERTY(Config)
bool bNavEnableKeyboard = false;
UPROPERTY(Config)
bool bResolveShortcutsConflicts = true;
UPROPERTY(Config)
FCogImGuiKeyInfo ToggleImguiInputShortcut = FCogImGuiKeyInfo(EKeys::F1);
UPROPERTY(Config)
FCogImGuiKeyInfo ToggleSelectionShortcut = FCogImGuiKeyInfo(EKeys::F5);
UPROPERTY(Config)
TArray<FCogImGuiKeyInfo> LoadLayoutShortcuts = { FCogImGuiKeyInfo(EKeys::F2), FCogImGuiKeyInfo(EKeys::F3), FCogImGuiKeyInfo(EKeys::F4), FCogImGuiKeyInfo()};
UPROPERTY(Config)
TArray<FCogImGuiKeyInfo> SaveLayoutShortcuts = { FCogImGuiKeyInfo(), FCogImGuiKeyInfo(), FCogImGuiKeyInfo(), FCogImGuiKeyInfo()};
//UPROPERTY(Config)
//bool bNavEnableGamepad = false;
@@ -97,5 +116,10 @@ public:
bNavEnableKeyboard = false;
//bNavEnableGamepad = false;
//bNavNoCaptureInput = true;
ToggleImguiInputShortcut = FCogImGuiKeyInfo(EKeys::F1);
ToggleSelectionShortcut = FCogImGuiKeyInfo(EKeys::F5);
LoadLayoutShortcuts = { FCogImGuiKeyInfo(EKeys::F2), FCogImGuiKeyInfo(EKeys::F3), FCogImGuiKeyInfo(EKeys::F4), FCogImGuiKeyInfo()};
SaveLayoutShortcuts = { FCogImGuiKeyInfo(), FCogImGuiKeyInfo(), FCogImGuiKeyInfo(), FCogImGuiKeyInfo()};
}
};