diff --git a/Plugins/CogImgui/Source/CogImgui/Private/CogImguiInputHelper.cpp b/Plugins/CogImgui/Source/CogImgui/Private/CogImguiInputHelper.cpp index a54e284..be8440c 100644 --- a/Plugins/CogImgui/Source/CogImgui/Private/CogImguiInputHelper.cpp +++ b/Plugins/CogImgui/Source/CogImgui/Private/CogImguiInputHelper.cpp @@ -85,16 +85,15 @@ bool FCogImguiInputHelper::WasKeyInfoJustPressed(APlayerController& PlayerContro { if (PlayerController.WasInputKeyJustPressed(KeyInfo.Key)) { - if (UPlayerInput* PlayerInput = PlayerController.PlayerInput.Get()) - { - const bool MatchCtrl = IsCheckBoxStateMatchingValue(KeyInfo.Ctrl, PlayerInput->IsCtrlPressed()); - const bool MatchAlt = IsCheckBoxStateMatchingValue(KeyInfo.Alt, PlayerInput->IsAltPressed()); - const bool MatchShift = IsCheckBoxStateMatchingValue(KeyInfo.Shift, PlayerInput->IsShiftPressed()); - const bool MatchCmd = IsCheckBoxStateMatchingValue(KeyInfo.Cmd, PlayerInput->IsCmdPressed()); + const FModifierKeysState& ModifierKeys = FSlateApplication::Get().GetModifierKeys(); - const bool Result = MatchCtrl && MatchAlt && MatchShift && MatchCmd; - return Result; - } + const bool MatchCtrl = IsCheckBoxStateMatchingValue(KeyInfo.Ctrl, ModifierKeys.IsControlDown()); + const bool MatchAlt = IsCheckBoxStateMatchingValue(KeyInfo.Alt, ModifierKeys.IsAltDown()); + const bool MatchShift = IsCheckBoxStateMatchingValue(KeyInfo.Shift, ModifierKeys.IsShiftDown()); + const bool MatchCmd = IsCheckBoxStateMatchingValue(KeyInfo.Cmd, ModifierKeys.IsCommandDown()); + + const bool Result = MatchCtrl && MatchAlt && MatchShift && MatchCmd; + return Result; } return false; diff --git a/Plugins/CogImgui/Source/CogImgui/Public/CogImguiKeyInfo.h b/Plugins/CogImgui/Source/CogImgui/Public/CogImguiKeyInfo.h index f369159..55d0e13 100644 --- a/Plugins/CogImgui/Source/CogImgui/Public/CogImguiKeyInfo.h +++ b/Plugins/CogImgui/Source/CogImgui/Public/CogImguiKeyInfo.h @@ -5,7 +5,7 @@ #include "CogImGuiKeyInfo.generated.h" USTRUCT() -struct FCogImGuiKeyInfo +struct COGIMGUI_API FCogImGuiKeyInfo { GENERATED_BODY() diff --git a/Plugins/CogWindow/Source/CogWindow/CogWindow.Build.cs b/Plugins/CogWindow/Source/CogWindow/CogWindow.Build.cs index ee055eb..df76e45 100644 --- a/Plugins/CogWindow/Source/CogWindow/CogWindow.Build.cs +++ b/Plugins/CogWindow/Source/CogWindow/CogWindow.Build.cs @@ -31,6 +31,7 @@ public class CogWindow : ModuleRules PrivateDependencyModuleNames.AddRange( new string[] { + "InputCore", "CoreUObject", "Engine", "Slate", diff --git a/Plugins/CogWindow/Source/CogWindow/Private/CogWindow.cpp b/Plugins/CogWindow/Source/CogWindow/Private/CogWindow.cpp index 514e319..51b9069 100644 --- a/Plugins/CogWindow/Source/CogWindow/Private/CogWindow.cpp +++ b/Plugins/CogWindow/Source/CogWindow/Private/CogWindow.cpp @@ -116,31 +116,6 @@ void UCogWindow::GameTick(float DeltaTime) { } -//-------------------------------------------------------------------------------------------------------------------------- -void UCogWindow::DrawMenuItem(const FString& MenuItemName) -{ - if (bShowInsideMenu) - { - ImGui::SetNextWindowSizeConstraints(ImVec2(FCogWindowWidgets::GetFontWidth() * 40, ImGui::GetTextLineHeightWithSpacing() * 1), - ImVec2(FCogWindowWidgets::GetFontWidth() * 50, ImGui::GetTextLineHeightWithSpacing() * 60)); - - if (ImGui::BeginMenu(TCHAR_TO_ANSI(*MenuItemName))) - { - RenderContent(); - ImGui::EndMenu(); - } - - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) - { - bIsVisible = !bIsVisible; - } - } - else - { - ImGui::MenuItem(TCHAR_TO_ANSI(*MenuItemName), nullptr, &bIsVisible); - } -} - //-------------------------------------------------------------------------------------------------------------------------- void UCogWindow::SetSelection(AActor* NewSelection) { diff --git a/Plugins/CogWindow/Source/CogWindow/Private/CogWindowManager.cpp b/Plugins/CogWindow/Source/CogWindow/Private/CogWindowManager.cpp index 6c68188..2045bba 100644 --- a/Plugins/CogWindow/Source/CogWindow/Private/CogWindowManager.cpp +++ b/Plugins/CogWindow/Source/CogWindow/Private/CogWindowManager.cpp @@ -4,6 +4,7 @@ #include "CogImguiModule.h" #include "CogImguiWidget.h" #include "CogWindow_Spacing.h" +#include "CogWindow_Settings.h" #include "CogWindowWidgets.h" #include "Engine/Engine.h" #include "imgui_internal.h" @@ -33,6 +34,8 @@ void UCogWindowManager::InitializeInternal() SpaceWindows.Add(CreateWindow("Space 2", false)); SpaceWindows.Add(CreateWindow("Space 3", false)); SpaceWindows.Add(CreateWindow("Space 4", false)); + + SettingsWindow = CreateWindow("Window.Settings", false); } //-------------------------------------------------------------------------------------------------------------------------- @@ -314,36 +317,9 @@ void UCogWindowManager::DrawMainMenu() ImGui::Separator(); - ImGui::MenuItem("Compact Mode", nullptr, &bCompactMode); - - ImGui::Text("DPI Scale"); - ImGui::SameLine(); - FCogWindowWidgets::PushStyleCompact(); - FCogWindowWidgets::SetNextItemToShortWidth(); - ImGui::SliderFloat("", &DPIScale, 0.5f, 2.0f, "%.2f"); - if (ImGui::IsItemDeactivatedAfterEdit()) - { - bRefreshDPIScale = true; - } - FCogWindowWidgets::PopStyleCompact(); - - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::TextUnformatted("Change DPi Scale [Mouse Wheel]"); - ImGui::TextUnformatted("Reset DPi Scale [Middle Mouse]"); - ImGui::EndTooltip(); - } - - ImGui::Separator(); - - ImGui::MenuItem("Show Window Help", nullptr, &bShowHelp); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::TextUnformatted("Should some help be displayed when the mouse is over a window title ?"); - ImGui::EndTooltip(); - } + DrawMenuItem(*SettingsWindow, "Settings"); + + ImGui::EndMenu(); } @@ -370,7 +346,7 @@ void UCogWindowManager::DrawMenu(UCogWindowManager::FMenu& Menu) { if (Menu.Window != nullptr) { - Menu.Window->DrawMenuItem(Menu.Name); + DrawMenuItem(*Menu.Window, TCHAR_TO_ANSI(*Menu.Name)); } else { @@ -385,6 +361,35 @@ void UCogWindowManager::DrawMenu(UCogWindowManager::FMenu& Menu) } } +//-------------------------------------------------------------------------------------------------------------------------- +void UCogWindowManager::DrawMenuItem(UCogWindow& Window, const char* MenuItemName) +{ + if (bShowWindowsInMainMenu) + { + ImGui::SetNextWindowSizeConstraints(ImVec2(FCogWindowWidgets::GetFontWidth() * 40, ImGui::GetTextLineHeightWithSpacing() * 1), + ImVec2(FCogWindowWidgets::GetFontWidth() * 50, ImGui::GetTextLineHeightWithSpacing() * 60)); + + if (ImGui::BeginMenu(MenuItemName)) + { + Window.RenderContent(); + ImGui::EndMenu(); + } + + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) + { + Window.SetIsVisible(!Window.GetIsVisible()); + } + } + else + { + bool bIsVisible = Window.GetIsVisible(); + if (ImGui::MenuItem(MenuItemName, nullptr, &bIsVisible)) + { + Window.SetIsVisible(bIsVisible); + } + } +} + //-------------------------------------------------------------------------------------------------------------------------- void UCogWindowManager::TickDPI() { @@ -392,15 +397,13 @@ void UCogWindowManager::TickDPI() const bool IsControlDown = ImGui::GetIO().KeyCtrl; if (IsControlDown && MouseWheel != 0) { - DPIScale = FMath::Clamp(DPIScale + (MouseWheel > 0 ? 0.05f : -0.05f), 0.5f, 2.0f); - bRefreshDPIScale = true; + SetDPIScale(FMath::Clamp(DPIScale + (MouseWheel > 0 ? 0.1f : -0.1f), 0.5f, 2.0f)); } const bool IsMiddleMouseClicked = ImGui::GetIO().MouseClicked[2]; if (IsControlDown && IsMiddleMouseClicked) { - DPIScale = 1.0f; - bRefreshDPIScale = true; + SetDPIScale(1.0f); } } @@ -456,4 +459,16 @@ void UCogWindowManager::SettingsHandler_WriteAll(ImGuiContext* Context, ImGuiSet Buffer->appendf("0x%08X\n", Window->GetID()); } } -} \ No newline at end of file +} + +//-------------------------------------------------------------------------------------------------------------------------- +void UCogWindowManager::SetDPIScale(float Value) +{ + if (DPIScale == Value) + { + return; + } + + DPIScale = Value; + bRefreshDPIScale = true; +} diff --git a/Plugins/CogWindow/Source/CogWindow/Private/CogWindowWidgets.cpp b/Plugins/CogWindow/Source/CogWindow/Private/CogWindowWidgets.cpp index 26c1833..0aca920 100644 --- a/Plugins/CogWindow/Source/CogWindow/Private/CogWindowWidgets.cpp +++ b/Plugins/CogWindow/Source/CogWindow/Private/CogWindowWidgets.cpp @@ -206,3 +206,72 @@ float FCogWindowWidgets::GetFontWidth() return ImGui::GetFontSize() * 0.5f; } +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogWindowWidgets::ComboboxEnum(const char* Label, UObject* Object, const char* FieldName, uint8* PointerToEnumValue) +{ + const FEnumProperty* EnumProperty = CastField(Object->GetClass()->FindPropertyByName(FName(FieldName))); + if (EnumProperty == nullptr) + { + return false; + } + + return ComboboxEnum(Label, EnumProperty, PointerToEnumValue); +} + +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogWindowWidgets::ComboboxEnum(const char* Label, const FEnumProperty* EnumProperty, uint8* PointerToValue) +{ + bool HasChanged = false; + + UEnum* Enum = EnumProperty->GetEnum(); + int64 EnumValue = EnumProperty->GetUnderlyingProperty()->GetSignedIntPropertyValue(PointerToValue); + FString EnumValueName = Enum->GetNameStringByValue(EnumValue); + + int64 NewValue; + if (ComboboxEnum(Label, Enum, EnumValue, NewValue)) + { + EnumProperty->GetUnderlyingProperty()->SetIntPropertyValue(PointerToValue, NewValue); + } + + return HasChanged; +} + +//-------------------------------------------------------------------------------------------------------------------------- +bool FCogWindowWidgets::ComboboxEnum(const char* Label, UEnum* Enum, int64 CurrentValue, int64& NewValue) +{ + bool HasChanged = false; + + FString CurrentEntryName = Enum->GetNameStringByValue(CurrentValue); + + if (ImGui::BeginCombo(Label, TCHAR_TO_ANSI(*CurrentEntryName))) + { + for (int32 EnumIndex = 0; EnumIndex < Enum->NumEnums() - 1; ++EnumIndex) + { + +#if WITH_EDITORONLY_DATA + bool bShouldBeHidden = Enum->HasMetaData(TEXT("Hidden"), EnumIndex) || Enum->HasMetaData(TEXT("Spacer"), EnumIndex); + if (bShouldBeHidden) + continue; +#endif //WITH_EDITORONLY_DATA + + FString EnumEntryName = Enum->GetNameStringByIndex(EnumIndex); + int64 EnumEntryValue = Enum->GetValueByIndex(EnumIndex); + + bool IsSelected = EnumEntryName == CurrentEntryName; + + if (ImGui::Selectable(TCHAR_TO_ANSI(*EnumEntryName), IsSelected)) + { + HasChanged = true; + NewValue = EnumEntryValue; + } + + if (IsSelected) + { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + + return HasChanged; +} \ No newline at end of file diff --git a/Plugins/CogWindow/Source/CogWindow/Private/CogWindow_Settings.cpp b/Plugins/CogWindow/Source/CogWindow/Private/CogWindow_Settings.cpp new file mode 100644 index 0000000..12b33a5 --- /dev/null +++ b/Plugins/CogWindow/Source/CogWindow/Private/CogWindow_Settings.cpp @@ -0,0 +1,89 @@ +#include "CogWindow_Settings.h" + +#include "CogImguiModule.h" +#include "InputCoreTypes.h" + +//-------------------------------------------------------------------------------------------------------------------------- +UCogWindow_Settings::UCogWindow_Settings() +{ + bHasMenu = false; +} + +//-------------------------------------------------------------------------------------------------------------------------- +void UCogWindow_Settings::PostInitProperties() +{ + Super::PostInitProperties(); + + FCogImguiModule::Get().SetToggleInputKey(ToggleInputKey); +} + +//-------------------------------------------------------------------------------------------------------------------------- +void UCogWindow_Settings::RenderContent() +{ + ImGui::Checkbox("Compact Mode", &GetOwner()->bCompactMode); + + ImGui::Checkbox("Show Windows In Main Menu", &GetOwner()->bShowWindowsInMainMenu); + + ImGui::Checkbox("Show Window Help", &GetOwner()->bShowHelp); + + FCogWindowWidgets::SetNextItemToShortWidth(); + ImGui::SliderFloat("DPI Scale", &GetOwner()->DPIScale, 0.5f, 2.0f, "%.1f"); + if (ImGui::IsItemDeactivatedAfterEdit()) + { + GetOwner()->bRefreshDPIScale = true; + } + + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::TextUnformatted("Change DPi Scale [Mouse Wheel]"); + ImGui::TextUnformatted("Reset DPi Scale [Middle Mouse]"); + ImGui::EndTooltip(); + } + + ImGui::Separator(); + + ImGui::Text("Toggle Input Key"); + + TArray Keys; + EKeys::GetAllKeys(Keys); + + bool HasKeyChanged = false; + FCogWindowWidgets::SetNextItemToShortWidth(); + if (ImGui::BeginCombo("Key", TCHAR_TO_ANSI(*ToggleInputKey.Key.ToString()))) + { + for (int32 i = 0; i < Keys.Num(); ++i) + { + const FKey Key = Keys[i]; + if (Key.IsDigital() == false || Key.IsDeprecated()) + { + continue; + } + + bool IsSelected = ToggleInputKey.Key == Key; + if (ImGui::Selectable(TCHAR_TO_ANSI(*Key.ToString()), IsSelected)) + { + ToggleInputKey.Key = Key; + HasKeyChanged = true; + } + } + ImGui::EndCombo(); + } + + FCogWindowWidgets::SetNextItemToShortWidth(); + HasKeyChanged |= FCogWindowWidgets::ComboboxEnum("Ctrl", ToggleInputKey.Ctrl); + + FCogWindowWidgets::SetNextItemToShortWidth(); + HasKeyChanged |= FCogWindowWidgets::ComboboxEnum("Shift", ToggleInputKey.Shift); + + FCogWindowWidgets::SetNextItemToShortWidth(); + HasKeyChanged |= FCogWindowWidgets::ComboboxEnum("Alt", ToggleInputKey.Alt); + + FCogWindowWidgets::SetNextItemToShortWidth(); + HasKeyChanged |= FCogWindowWidgets::ComboboxEnum("Cmd", ToggleInputKey.Cmd); + + if (HasKeyChanged) + { + FCogImguiModule::Get().SetToggleInputKey(ToggleInputKey); + } +} diff --git a/Plugins/CogWindow/Source/CogWindow/Public/CogWindow.h b/Plugins/CogWindow/Source/CogWindow/Public/CogWindow.h index 56407db..44bad57 100644 --- a/Plugins/CogWindow/Source/CogWindow/Public/CogWindow.h +++ b/Plugins/CogWindow/Source/CogWindow/Public/CogWindow.h @@ -28,9 +28,6 @@ public: /** Called every frame without a valid imgui context (outside of the imgui NewFrame/EndFrame) even if the window is hidden. */ virtual void GameTick(float DeltaTime); - /** Draw the window menu item. Called when the menu item visible */ - virtual void DrawMenuItem(const FString& MenuItemName); - virtual void DrawMainMenuWidget(bool Draw, float& Width) {} ImGuiID GetID() const { return ID; } @@ -56,6 +53,8 @@ public: UCogWindowManager* GetOwner() const { return Owner; } protected: + + friend class UCogWindowManager; virtual const FString& GetTitle() const { return Name; } diff --git a/Plugins/CogWindow/Source/CogWindow/Public/CogWindowManager.h b/Plugins/CogWindow/Source/CogWindow/Public/CogWindowManager.h index fc59cda..01e8e8a 100644 --- a/Plugins/CogWindow/Source/CogWindow/Public/CogWindowManager.h +++ b/Plugins/CogWindow/Source/CogWindow/Public/CogWindowManager.h @@ -6,6 +6,7 @@ #include "CogWindowManager.generated.h" class UCogWindow; +class UCogWindow_Settings; class UWorld; class SCogImguiWidget; struct ImGuiSettingsHandler; @@ -55,12 +56,26 @@ public: void SetHideAllWindows(bool Value); + float GetDPIScale() const { return DPIScale; } + + void SetDPIScale(float Value); + bool GetCompactMode() const { return bCompactMode; } + void SetCompactMode(bool Value) { bCompactMode = Value; } + bool GetShowHelp() const { return bShowHelp; } + void SetShowHelp(bool Value) { bShowHelp = Value; } + + bool GetPreviewWindowsInMenu() const { return bShowWindowsInMainMenu; } + + void SetPreviewWindowsInMenu(bool Value) { bShowWindowsInMainMenu = Value; } + protected: + friend class UCogWindow_Settings; + struct FMenu { FString Name; @@ -78,6 +93,8 @@ protected: void DrawMenu(FMenu& Menu); + void DrawMenuItem(UCogWindow& Window, const char* MenuItemName); + static void SettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*); static void SettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*); @@ -96,6 +113,9 @@ protected: UPROPERTY() TArray SpaceWindows; + UPROPERTY() + UCogWindow_Settings* SettingsWindow = nullptr; + UPROPERTY() TArray MainMenuWidgets; @@ -111,7 +131,10 @@ protected: UPROPERTY(Config) bool bShowHelp = true; - TSharedPtr ImGuiWidget; + UPROPERTY(Config) + bool bShowWindowsInMainMenu = true; + + TSharedPtr ImGuiWidget = nullptr; FMenu MainMenu; @@ -121,5 +144,5 @@ protected: bool bHideAllWindows = false; - bool bRefreshDPIScale; + bool bRefreshDPIScale = false; }; diff --git a/Plugins/CogWindow/Source/CogWindow/Public/CogWindowWidgets.h b/Plugins/CogWindow/Source/CogWindow/Public/CogWindowWidgets.h index c816b23..ea726f5 100644 --- a/Plugins/CogWindow/Source/CogWindow/Public/CogWindowWidgets.h +++ b/Plugins/CogWindow/Source/CogWindow/Public/CogWindowWidgets.h @@ -2,6 +2,10 @@ #include "CoreMinimal.h" #include "imgui.h" +#include "UObject/ReflectedTypeAccessors.h" + +class UEnum; +class FEnumProperty; class COGWINDOW_API FCogWindowWidgets { @@ -34,4 +38,36 @@ public: static void SetNextItemToShortWidth(); static float GetFontWidth(); + + template + static bool ComboboxEnum(const char* Label, const EnumType CurrentValue, EnumType& NewValue); + + template + static bool ComboboxEnum(const char* Label, EnumType& Value); + + static bool ComboboxEnum(const char* Label, UEnum* Enum, int64 CurrentValue, int64& NewValue); + + static bool ComboboxEnum(const char* Label, UObject* Object, const char* FieldName, uint8* PointerToEnumValue); + + static bool ComboboxEnum(const char* Label, const FEnumProperty* EnumProperty, uint8* PointerToEnumValue); + }; + +template +bool FCogWindowWidgets::ComboboxEnum(const char* Label, const EnumType CurrentValue, EnumType& NewValue) +{ + int64 NewValueInt; + if (ComboboxEnum(Label, StaticEnum(), (int64)CurrentValue, NewValueInt)) + { + NewValue = (EnumType)NewValueInt; + return true; + } + + return false; +} + +template +bool FCogWindowWidgets::ComboboxEnum(const char* Label, EnumType& Value) +{ + return ComboboxEnum(Label, Value, Value); +} \ No newline at end of file diff --git a/Plugins/CogWindow/Source/CogWindow/Public/CogWindow_Settings.h b/Plugins/CogWindow/Source/CogWindow/Public/CogWindow_Settings.h new file mode 100644 index 0000000..28a473d --- /dev/null +++ b/Plugins/CogWindow/Source/CogWindow/Public/CogWindow_Settings.h @@ -0,0 +1,27 @@ +#pragma once + +#include "CoreMinimal.h" +#include "CogWindow.h" +#include "CogImGuiKeyInfo.h" +#include "CogWindow_Settings.generated.h" + +UCLASS(Config = Cog) +class COGWINDOW_API UCogWindow_Settings : public UCogWindow +{ + GENERATED_BODY() + +public: + + UCogWindow_Settings(); + +protected: + + virtual void PostInitProperties() override; + + virtual void RenderContent() override; + +private: + + UPROPERTY(Config) + FCogImGuiKeyInfo ToggleInputKey; +}; diff --git a/Source/CogSample/CogSampleGameState.cpp b/Source/CogSample/CogSampleGameState.cpp index 47b6374..f9acd4c 100644 --- a/Source/CogSample/CogSampleGameState.cpp +++ b/Source/CogSample/CogSampleGameState.cpp @@ -117,7 +117,7 @@ void ACogSampleGameState::Tick(float DeltaSeconds) //-------------------------------------------------------------------------------------------------------------------------- void ACogSampleGameState::InitializeCog() { - FCogImguiModule::Get().SetToggleInputKey(FCogImGuiKeyInfo(EKeys::Insert)); + FCogImguiModule::Get().SetToggleInputKey(FCogImGuiKeyInfo(EKeys::Tab)); RegisterCommand(TEXT("Cog.ToggleInput"), TEXT(""), FConsoleCommandWithArgsDelegate::CreateUObject(this, &ACogSampleGameState::CogToggleInput)); CogWindowManager = NewObject(this);