CogWindow: simplify how CogWidgets are rendered

Remove the need to specify the widgets width to be able to right them.
Instead widgets are rendered in a table which left/center/right align automatically.
This commit is contained in:
Arnaud Jamin
2025-01-30 13:15:25 -05:00
parent fff036d81f
commit 1cecf93841
28 changed files with 386 additions and 323 deletions
+1
View File
@@ -69,6 +69,7 @@ bCaptureMouseOnLaunch=True
bEnableLegacyInputScales=True
bEnableMotionControls=True
bFilterInputByPlatformUser=False
bEnableInputDeviceSubsystem=True
bShouldFlushPressedKeysOnViewportFocusLost=True
bEnableDynamicComponentInputBinding=True
bAlwaysShowTouchInterface=False
@@ -243,7 +243,7 @@ void FCogEngineWindow_Cheats::RenderContent()
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -256,7 +256,7 @@ void FCogEngineWindow_Inspector::RenderMenu()
//-----------------------------------
// Search
//-----------------------------------
FCogWindowWidgets::SearchBar(Filter, -FCogWindowWidgets::GetFontWidth() * 9);
FCogWindowWidgets::SearchBar("##Filter", Filter, -FCogWindowWidgets::GetFontWidth() * 9);
//-----------------------------------
// Options
@@ -184,7 +184,7 @@ void FCogEngineWindow_OutputLog::RenderContent()
ImGui::EndCombo();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -15,6 +15,7 @@
#include "GameFramework/Character.h"
#include "HAL/IConsoleManager.h"
#include "imgui.h"
#include "imgui_internal.h"
#include "Kismet/GameplayStatics.h"
FString FCogEngineWindow_Selection::ToggleSelectionModeCommand = TEXT("Cog.ToggleSelectionMode");
@@ -25,7 +26,7 @@ void FCogEngineWindow_Selection::Initialize()
Super::Initialize();
bHasMenu = true;
bHasWidget = true;
bHasWidget = 2;
ActorClasses = { AActor::StaticClass(), ACharacter::StaticClass() };
Config = GetConfig<UCogEngineConfig_Selection>();
@@ -294,77 +295,30 @@ void FCogEngineWindow_Selection::TickSelectionMode()
}
//--------------------------------------------------------------------------------------------------------------------------
float FCogEngineWindow_Selection::GetMainMenuWidgetWidth(int32 SubWidgetIndex, float MaxWidth)
void FCogEngineWindow_Selection::RenderMainMenuWidget()
{
switch (SubWidgetIndex)
if (ImGui::MenuItem("Pick"))
{
case 0: return FCogWindowWidgets::GetFontWidth() * 6;
case 1: return FMath::Min(FMath::Max(MaxWidth, FCogWindowWidgets::GetFontWidth() * 10), FCogWindowWidgets::GetFontWidth() * 30);
case 2: return FCogWindowWidgets::GetFontWidth() * 3;
GetOwner()->SetActivateSelectionMode(true);
HackWaitInputRelease();
}
RenderPickButtonTooltip();
return -1.0f;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Selection::RenderMainMenuWidget(int32 SubWidgetIndex, float Width)
{
//-----------------------------------
// Pick Button
//-----------------------------------
if (SubWidgetIndex == 0)
//TODO: Could be replaced by a BeginMenu
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
AActor* NewSelection = nullptr;
if (FCogWindowWidgets::MenuActorsCombo(
"MenuActorSelection",
NewSelection,
*GetWorld(),
ActorClasses,
Config->SelectedClassIndex,
&Filter,
GetLocalPlayerPawn(),
[this](AActor& Actor) { RenderActorContextMenu(Actor); }))
{
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
if (ImGui::Button("Pick", ImVec2(Width, 0)))
{
GetOwner()->SetActivateSelectionMode(true);
HackWaitInputRelease();
}
RenderPickButtonTooltip();
ImGui::PopStyleColor(1);
ImGui::PopStyleVar(2);
}
else if (SubWidgetIndex == 1)
{
ImGui::SetNextItemWidth(Width);
AActor* NewSelection = nullptr;
if (FCogWindowWidgets::MenuActorsCombo(
"MenuActorSelection",
NewSelection,
*GetWorld(),
ActorClasses,
Config->SelectedClassIndex,
&Filter,
GetLocalPlayerPawn(),
[this](AActor& Actor) { RenderActorContextMenu(Actor); }))
{
SetGlobalSelection(NewSelection);
}
}
else if (SubWidgetIndex == 2)
{
//-----------------------------------
// Reset Button
//-----------------------------------
{
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
if (ImGui::Button("X", ImVec2(Width, 0)))
{
SetGlobalSelection(nullptr);
ImGui::CloseCurrentPopup();
}
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Reset the selection to the controlled actor.");
}
ImGui::PopStyleColor(1);
ImGui::PopStyleVar(1);
}
SetGlobalSelection(NewSelection);
}
}
@@ -111,7 +111,7 @@ void FCogEngineWindow_Skeleton::RenderContent()
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -17,7 +17,7 @@ void FCogEngineWindow_Stats::Initialize()
{
Super::Initialize();
bHasWidget = true;
bHasWidget = 2;
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -64,30 +64,14 @@ void FCogEngineWindow_Stats::RenderContent()
}
//--------------------------------------------------------------------------------------------------------------------------
float FCogEngineWindow_Stats::GetMainMenuWidgetWidth(const int32 SubWidgetIndex, float MaxWidth)
void FCogEngineWindow_Stats::RenderMainMenuWidget()
{
const APlayerController* PlayerController = GetLocalPlayerController();
const UNetConnection* Connection = PlayerController != nullptr ? PlayerController->GetNetConnection() : nullptr;
switch (SubWidgetIndex)
{
case 0: return FCogWindowWidgets::GetFontWidth() * 8;
case 1: return Connection != nullptr ? FCogWindowWidgets::GetFontWidth() * 7 : 0.0f;
case 2: return Connection != nullptr ? FCogWindowWidgets::GetFontWidth() * 7 : 0.0f;
}
return -1;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Stats::RenderMainMenuWidget(const int32 SubWidgetIndex, const float Width)
{
switch (SubWidgetIndex)
{
case 0: RenderMainMenuWidgetFramerate(Width); break;
case 1: RenderMainMenuWidgetPing(Width); break;
case 2: RenderMainMenuWidgetPacketLoss(Width); break;
}
RenderMainMenuWidgetFramerate(FCogWindowWidgets::GetFontWidth() * 8);
RenderMainMenuWidgetPing(Connection != nullptr ? FCogWindowWidgets::GetFontWidth() * 7 : 0.0f);
RenderMainMenuWidgetPacketLoss(Connection != nullptr ? FCogWindowWidgets::GetFontWidth() * 7 : 0.0f);
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -96,22 +80,12 @@ void FCogEngineWindow_Stats::RenderMainMenuWidgetFramerate(const float Width)
extern ENGINE_API float GAverageFPS;
const int32 Fps = (int32)GAverageFPS;
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_Text, GetFpsColor(Fps));
if (ImGui::Button(TCHAR_TO_ANSI(*FString::Printf(TEXT("%3dfps###FramerateButton"), Fps)), ImVec2(Width, 0.0f)))
{
ImGui::OpenPopup("FrameratePopup");
}
const bool Open = ImGui::BeginMenu(TCHAR_TO_ANSI(*FString::Printf(TEXT("%3dfps###FramerateButton"), Fps)));
ImGui::PopStyleColor(2);
ImGui::PopStyleVar(2);
ImGui::SetItemTooltip("Framerate");
if (ImGui::BeginPopup("FrameratePopup"))
if (Open)
{
ImGui::Text("Fps");
ImGui::SameLine();
@@ -123,8 +97,10 @@ void FCogEngineWindow_Stats::RenderMainMenuWidgetFramerate(const float Width)
GEngine->SetMaxFPS(MaxFps);
}
ImGui::EndPopup();
ImGui::EndMenu();
}
ImGui::SetItemTooltip("Framerate");
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -138,25 +114,15 @@ void FCogEngineWindow_Stats::RenderMainMenuWidgetPing(const float Width)
}
const float Ping = PlayerState->GetPingInMilliseconds();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_Text, GetPingColor(Ping));
if (ImGui::Button(TCHAR_TO_ANSI(*FString::Printf(TEXT("%3dms###PingButton"), (int32)Ping)), ImVec2(Width, 0.0f)))
{
ImGui::OpenPopup("PingPopup");
}
const bool Open = ImGui::BeginMenu(TCHAR_TO_ANSI(*FString::Printf(TEXT("%3dms###PingButton"), (int32)Ping)));
ImGui::PopStyleColor(2);
ImGui::PopStyleVar(2);
ImGui::SetItemTooltip("Ping");
#if DO_ENABLE_NET_TEST
if (ImGui::BeginPopup("PingPopup"))
if (Open)
{
FWorldContext& WorldContext = GEngine->GetWorldContextFromWorldChecked(GetWorld());
if (WorldContext.ActiveNetDrivers.Num() > 0)
{
@@ -171,9 +137,11 @@ void FCogEngineWindow_Stats::RenderMainMenuWidgetPing(const float Width)
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
}
}
ImGui::EndPopup();
ImGui::EndMenu();
}
#endif //DO_ENABLE_NET_TEST
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -208,7 +176,6 @@ void FCogEngineWindow_Stats::RenderMainMenuWidgetPacketLoss(const float Width)
#if DO_ENABLE_NET_TEST
if (ImGui::BeginPopup("PacketLossPopup"))
{
FWorldContext& WorldContext = GEngine->GetWorldContextFromWorldChecked(GetWorld());
if (WorldContext.ActiveNetDrivers.Num() > 0)
{
@@ -45,9 +45,7 @@ protected:
virtual void RenderContent() override;
virtual float GetMainMenuWidgetWidth(int32 SubWidgetIndex, float MaxWidth) override;
virtual void RenderMainMenuWidget(int32 SubWidgetIndex, float Width) override;
virtual void RenderMainMenuWidget() override;
virtual bool DrawSelectionCombo();
@@ -23,9 +23,7 @@ protected:
virtual void RenderContent() override;
virtual float GetMainMenuWidgetWidth(int32 SubWidgetIndex, float MaxWidth) override;
virtual void RenderMainMenuWidget(int32 SubWidgetIndex, float Width) override;
virtual void RenderMainMenuWidget() override;
virtual void RenderMainMenuWidgetPacketLoss(float Width);
@@ -25,8 +25,8 @@
static UPlayerInput* GetPlayerInput(const UWorld* World);
FCogImGuiContextScope::
FCogImGuiContextScope(FCogImguiContext& CogImguiContext)
//--------------------------------------------------------------------------------------------------------------------------
FCogImGuiContextScope::FCogImGuiContextScope(FCogImguiContext& CogImguiContext)
{
PrevContext = ImGui::GetCurrentContext();
PrevPlotContext = ImPlot::GetCurrentContext();
@@ -35,8 +35,8 @@ FCogImGuiContextScope(FCogImguiContext& CogImguiContext)
ImPlot::SetCurrentContext(CogImguiContext.PlotContext);
}
FCogImGuiContextScope::
FCogImGuiContextScope(ImGuiContext* GuiCtx, ImPlotContext* PlotCtx)
//--------------------------------------------------------------------------------------------------------------------------
FCogImGuiContextScope::FCogImGuiContextScope(ImGuiContext* GuiCtx, ImPlotContext* PlotCtx)
{
PrevContext = ImGui::GetCurrentContext();
PrevPlotContext = ImPlot::GetCurrentContext();
@@ -45,8 +45,8 @@ FCogImGuiContextScope(ImGuiContext* GuiCtx, ImPlotContext* PlotCtx)
ImPlot::SetCurrentContext(PlotCtx);
}
FCogImGuiContextScope::
~FCogImGuiContextScope()
//--------------------------------------------------------------------------------------------------------------------------
FCogImGuiContextScope::~FCogImGuiContextScope()
{
ImGui::SetCurrentContext(PrevContext);
ImPlot::SetCurrentContext(PrevPlotContext);
@@ -298,11 +298,14 @@ bool FCogImguiContext::BeginFrame(float InDeltaTime)
//-------------------------------------------------------------------------------------------------------
// Refresh modifiers otherwise, when pressing ALT-TAB, the Alt modifier is always true
//-------------------------------------------------------------------------------------------------------
FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys();
if (ModifierKeys.IsControlDown() != IO.KeyCtrl) { IO.AddKeyEvent(ImGuiMod_Ctrl, ModifierKeys.IsControlDown()); }
if (ModifierKeys.IsShiftDown() != IO.KeyShift) { IO.AddKeyEvent(ImGuiMod_Shift, ModifierKeys.IsShiftDown()); }
if (ModifierKeys.IsAltDown() != IO.KeyAlt) { IO.AddKeyEvent(ImGuiMod_Alt, ModifierKeys.IsAltDown()); }
if (ModifierKeys.IsCommandDown() != IO.KeySuper) { IO.AddKeyEvent(ImGuiMod_Super, ModifierKeys.IsCommandDown()); }
if (bEnableInput)
{
FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys();
if (ModifierKeys.IsControlDown() != IO.KeyCtrl) { IO.AddKeyEvent(ImGuiMod_Ctrl, ModifierKeys.IsControlDown()); }
if (ModifierKeys.IsShiftDown() != IO.KeyShift) { IO.AddKeyEvent(ImGuiMod_Shift, ModifierKeys.IsShiftDown()); }
if (ModifierKeys.IsAltDown() != IO.KeyAlt) { IO.AddKeyEvent(ImGuiMod_Alt, ModifierKeys.IsAltDown()); }
if (ModifierKeys.IsCommandDown() != IO.KeySuper) { IO.AddKeyEvent(ImGuiMod_Super, ModifierKeys.IsCommandDown()); }
}
}
//-------------------------------------------------------------------------------------------------------
@@ -685,6 +688,8 @@ static UPlayerInput* GetPlayerInput(const UWorld* World)
//--------------------------------------------------------------------------------------------------------------------------
void FCogImguiContext::SetEnableInput(bool Value)
{
FCogImGuiContextScope ImGuiContextScope(ImGuiContext, PlotContext);
bEnableInput = Value;
if (FSlateApplication::IsInitialized() == false)
@@ -715,6 +720,14 @@ void FCogImguiContext::SetEnableInput(bool Value)
{
LocalPlayer->GetSlateOperations().CaptureMouse(GameViewport->GetGameViewportWidget().ToSharedRef());
}
//---------------------------------------------------------------------------------
// Make sure no keys stay down after disabling inputs
//---------------------------------------------------------------------------------
ImGuiIO& IO = ImGui::GetIO();
IO.ClearInputMouse();
IO.ClearEventsQueue();
IO.ClearInputKeys();
}
RefreshMouseCursor();
@@ -118,6 +118,11 @@ FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterE
{
FCogImGuiContextScope ImGuiContextScope(*Context);
if (Context->GetEnableInput() == false)
{
return FReply::Unhandled();
}
ImGuiIO& IO = ImGui::GetIO();
IO.AddInputCharacter(FCogImguiInputHelper::CastInputChar(CharacterEvent.GetCharacter()));
@@ -69,7 +69,7 @@ void FCogWindow::Render(float DeltaTime)
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
}
if (ImGui::Begin(TCHAR_TO_ANSI(*WindowTitle), &bIsVisible, WindowFlags))
{
if (bNoPadding)
@@ -205,3 +205,9 @@ UWorld* FCogWindow::GetWorld() const
{
return Owner->GetWorld();
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindow::IsWindowRenderedInMainMenu()
{
return Owner->IsRenderingMainMenu();
}
@@ -235,7 +235,7 @@ void UCogWindowManager::Render(float DeltaTime)
Window->Render(DeltaTime);
}
}
if (bCompactSaved)
{
FCogWindowWidgets::PopStyleCompact();
@@ -370,6 +370,8 @@ void UCogWindowManager::RenderMainMenu()
{
const UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GetWorld());
IsRenderingInMainMenu = true;
if (ImGui::BeginMainMenuBar())
{
for (FMenu& Menu : MainMenu.SubMenus)
@@ -402,116 +404,107 @@ void UCogWindowManager::RenderMainMenu()
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Widgets"))
{
for (int32 i = 0; i < Widgets.Num(); ++i)
{
FCogWindow* Window = Widgets[i];
ImGui::PushID(i);
bool Visible = Window->GetIsWidgetVisible();
if (ImGui::Checkbox(TCHAR_TO_ANSI(*Window->GetName()), &Visible))
{
Window->SetIsWidgetVisible(Visible);
}
if (ImGui::IsItemActive() && ImGui::IsItemHovered() == false)
{
const int iNext = i + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
if (iNext >= 0 && iNext < Widgets.Num())
{
Widgets[i] = Widgets[iNext];
Widgets[iNext] = Window;
ImGui::ResetMouseDragDelta();
}
}
if (i == 0)
{
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("Drag and drop the widget names to reorder them.");
}
ImGui::PopID();
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
const float MinCursorX = ImGui::GetCursorPosX();
float CursorX = ImGui::GetWindowWidth();
//------------------------------------------------------------
// Render in reverse order because it makes more sense
// when looking at the widget ordered list in the UI.
//------------------------------------------------------------
for (int32 WindowIndex = Widgets.Num() - 1; WindowIndex >= 0; WindowIndex--)
{
FCogWindow* Window = Widgets[WindowIndex];
if (Window->GetIsWidgetVisible() == false)
{
continue;
}
TArray<float> SubWidgetsWidths;
float SimCursorX = CursorX;
for (int32 SubWidgetIndex = 0; ; ++SubWidgetIndex)
{
const float MaxWidth = SimCursorX - MinCursorX;
float SubWidgetWidth = Window->GetMainMenuWidgetWidth(SubWidgetIndex, MaxWidth);
if (SubWidgetWidth == -1)
{
break;
}
SimCursorX -= SubWidgetWidth;
SubWidgetsWidths.Add(SubWidgetWidth);
}
bool Stop = false;
for (int32 SubWidgetIndex = SubWidgetsWidths.Num() - 1; SubWidgetIndex >= 0; SubWidgetIndex--)
{
const float SubWidgetWidth = SubWidgetsWidths[SubWidgetIndex];
const float MaxWidth = CursorX - MinCursorX;
//-------------------------------------------
// Bypass this subwidget if its width is 0
//-------------------------------------------
if (SubWidgetWidth == 0)
{
continue;
}
//-------------------------------------------
// Stop drawing if there is not enough room
//-------------------------------------------
if (SubWidgetWidth > MaxWidth)
{
Stop = true;
break;
}
CursorX -= SubWidgetWidth;
ImGui::SetCursorPosX(CursorX);
Window->RenderMainMenuWidget(SubWidgetIndex, SubWidgetWidth);
}
if (Stop)
{
break;
}
CursorX -= ImGui::GetStyle().ItemSpacing.x;
}
RenderWidgets();
ImGui::EndMainMenuBar();
}
IsRenderingInMainMenu = false;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogWindowManager::RenderWidgets()
{
int32 numVisibleWidgets = 0;
for (int i = 0; i < Widgets.Num(); ++i)
{
FCogWindow* Window = Widgets[i];
if (Window->GetIsWidgetVisible())
{
numVisibleWidgets++;
}
}
if (numVisibleWidgets == 0)
{ return; }
int32 numColumns = numVisibleWidgets;
if (Settings->WidgetAlignment == ECogWidgetAlignment::Right)
{
numColumns++;
}
else if (Settings->WidgetAlignment == ECogWidgetAlignment::Center)
{
numColumns += 2;
}
ImGuiTableFlags Flags = ImGuiTableFlags_None;
if (Settings->ShowWidgetBorders)
{
Flags |= ImGuiTableFlags_BordersInnerV;
if (Settings->WidgetAlignment == ECogWidgetAlignment::Left)
{
Flags |= ImGuiTableFlags_BordersOuterV;
}
}
if (Settings->WidgetAlignment == ECogWidgetAlignment::Manual)
{
Flags |= ImGuiTableFlags_Resizable;
if (Settings->ShowWidgetBorders == false)
{
Flags |= ImGuiTableFlags_NoBordersInBodyUntilResize;
}
}
if (ImGui::BeginTable("Widgets", numColumns, Flags))
{
if (Settings->WidgetAlignment == ECogWidgetAlignment::Right || Settings->WidgetAlignment == ECogWidgetAlignment::Center)
{
ImGui::TableSetupColumn("Stretch", ImGuiTableColumnFlags_WidthStretch);
}
for (int i = 0; i < numVisibleWidgets; ++i)
{
ImGui::TableSetupColumn("Fixed", ImGuiTableColumnFlags_WidthFixed);
}
if (Settings->WidgetAlignment == ECogWidgetAlignment::Center)
{
ImGui::TableSetupColumn("Stretch", ImGuiTableColumnFlags_WidthStretch);
}
ImGui::TableNextRow();
if (Settings->WidgetAlignment == ECogWidgetAlignment::Right || Settings->WidgetAlignment == ECogWidgetAlignment::Center)
{
ImGui::TableNextColumn();
}
for (int i = 0; i < Widgets.Num(); ++i)
{
FCogWindow* Window = Widgets[i];
if (Window->GetIsWidgetVisible() == false)
{ continue; }
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 2);
Window->RenderMainMenuWidget();
}
if (Settings->WidgetAlignment == ECogWidgetAlignment::Center)
{
ImGui::TableNextColumn();
}
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -553,7 +546,7 @@ void UCogWindowManager::RenderMenuItem(FCogWindow& Window, const char* MenuItemN
{
Window.SetIsVisible(!Window.GetIsVisible());
}
RenderMenuItemHelp(Window);
}
else
@@ -41,15 +41,17 @@ void FCogWindowWidgets::EndTableTooltip()
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowWidgets::ItemTooltipWrappedText(const char* InText)
bool FCogWindowWidgets::ItemTooltipWrappedText(const char* InText)
{
if (ImGui::BeginItemTooltip())
{
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(InText);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
bool result = ImGui::BeginItemTooltip();
if (result == false)
{ return false; }
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(InText);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -272,26 +274,19 @@ void FCogWindowWidgets::AddTextWithShadow(ImDrawList* DrawList, const ImVec2& Po
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowWidgets::SearchBar(ImGuiTextFilter& Filter, float Width /*= -1*/)
bool FCogWindowWidgets::SearchBar(const char* InLabel, ImGuiTextFilter& InFilter, float InWidth /*= -1*/)
{
const ImGuiWindow* Window = FCogImguiHelper::GetCurrentWindow();
const ImVec2 Pos1 = Window->DC.CursorPos;
Filter.Draw("##Filter", Width);
const ImVec2 Pos2 = Window->DC.CursorPosPrevLine;
if (ImGui::IsItemActive() == false && Filter.Filters.empty())
if (InWidth != 0.0f)
{
static const char* Text = "Search";
const float Height = ImGui::GetFrameHeight();
const ImGuiContext& g = *ImGui::GetCurrentContext();
const ImVec2 Min = Pos1 + ImVec2(g.Style.ItemSpacing.x, 0.0f);
const ImVec2 Max = Pos2 + ImVec2(-g.Style.ItemSpacing.x, Height);
const ImRect BB(Min, Max);
const ImVec2 TextSize = ImGui::CalcTextSize(Text, nullptr);
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 128));
ImGui::RenderTextClipped(Min, Max, Text, nullptr, &TextSize, ImVec2(0.0f, 0.5f), &BB);
ImGui::PopStyleColor();
ImGui::SetNextItemWidth(InWidth);
}
//
bool value_changed = ImGui::InputTextWithHint(InLabel, "Search", InFilter.InputBuf, IM_ARRAYSIZE(InFilter.InputBuf));
if (value_changed)
{
InFilter.Build();
}
return value_changed;
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -859,7 +854,7 @@ bool FCogWindowWidgets::ActorsListWithFilters(AActor*& NewSelection, const UWorl
if (Filter != nullptr)
{
ImGui::SameLine();
SearchBar(*Filter);
SearchBar("##Filter", *Filter);
AddSeparator = true;
}
@@ -1121,15 +1116,30 @@ void FCogWindowWidgets::SmallButton(const char* Text, const ImVec4& Color)
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::InputText(const char* Text, FString& Value)
bool FCogWindowWidgets::InputText(const char* Text, FString& Value, ImGuiInputTextFlags InFlags, ImGuiInputTextCallback InCallback, void* InUserData)
{
static char Buffer[256] = "";
ImStrncpy(Buffer, TCHAR_TO_ANSI(*Value), IM_ARRAYSIZE(Buffer));
static char ValueBuffer[256] = "";
ImStrncpy(ValueBuffer, TCHAR_TO_ANSI(*Value), IM_ARRAYSIZE(ValueBuffer));
bool result = ImGui::InputText(Text, Buffer, IM_ARRAYSIZE(Buffer));
bool result = ImGui::InputText(Text, ValueBuffer, IM_ARRAYSIZE(ValueBuffer), InFlags, InCallback, InUserData);
if (result)
{
Value = FString(Buffer);
Value = FString(ValueBuffer);
}
return result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::InputTextWithHint(const char* InText, const char* InHint, FString& InValue, ImGuiInputTextFlags InFlags, ImGuiInputTextCallback InCallback, void* InUserData)
{
static char ValueBuffer[256] = "";
ImStrncpy(ValueBuffer, TCHAR_TO_ANSI(*InValue), IM_ARRAYSIZE(ValueBuffer));
bool result = ImGui::InputTextWithHint(InText, InHint, ValueBuffer, IM_ARRAYSIZE(ValueBuffer), InFlags, InCallback, InUserData);
if (result)
{
InValue = FString(ValueBuffer);
}
return result;
@@ -1142,6 +1152,7 @@ bool FCogWindowWidgets::BeginRightAlign(const char* Id)
{
ImGui::TableSetupColumn("a", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TableNextColumn();
return true;
@@ -1266,7 +1277,48 @@ bool FCogWindowWidgets::OpenObjectAssetButton(const UObject* InObject, const ImV
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowWidgets::RenderClosebutton(const ImVec2& InPos)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
// Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825)
// This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible?
const ImRect bb(InPos, InPos + ImVec2(g.FontSize, g.FontSize));
ImU32 cross_col = ImGui::GetColorU32(ImGuiCol_Text);
ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
}
// //--------------------------------------------------------------------------------------------------------------------------
// bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags)
// {
// ImGuiContext& g = *GImGui;
// ImGuiWindow* window = GetCurrentWindow();
// if (window->SkipItems)
// return false;
//
// const ImGuiID id = window->GetID(str_id);
// const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
// const float default_size = GetFrameHeight();
// ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f);
// if (!ItemAdd(bb, id))
// return false;
//
// bool hovered, held;
// bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
//
// // Render
// const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
// const ImU32 text_col = GetColorU32(ImGuiCol_Text);
// RenderNavCursor(bb, id);
// RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
// RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir);
//
// IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags);
// return pressed;
// }
@@ -173,6 +173,68 @@ void FCogWindow_Settings::RenderContent()
}
}
//-------------------------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Widgets (?)", ImGuiTreeNodeFlags_DefaultOpen))
{
FCogWindowWidgets::ItemTooltipWrappedText("Widgets appear in the main menu bar.");
ImGui::Checkbox("Show Widget Borders", &Config->ShowWidgetBorders);
FCogWindowWidgets::ItemTooltipWrappedText("Should a border be visible between widgets.");
FCogWindowWidgets::SetNextItemToShortWidth();
FCogWindowWidgets::ComboboxEnum("Widgets Alignment", Config->WidgetAlignment);
FCogWindowWidgets::ItemTooltipWrappedText("How the widgets should be aligned in the main menu bar.");
if (ImGui::BeginChild("Widgets", ImVec2(0, ImGui::GetFontSize() * 10), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_MenuBar))
{
if (ImGui::BeginMenuBar())
{
ImGui::TextUnformatted("Widgets visibility and ordering");
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("Drag and drop the widget names to reorder them.");
ImGui::EndMenuBar();
}
TArray<FCogWindow*>& Widgets = GetOwner()->Widgets;
for (int32 i = 0; i < Widgets.Num(); ++i)
{
FCogWindow* Window = Widgets[i];
ImGui::PushID(i);
bool Visible = Window->GetIsWidgetVisible();
if (ImGui::Checkbox("##Visibility", &Visible))
{
Window->SetIsWidgetVisible(Visible);
}
ImGui::SameLine();
ImGui::Selectable(TCHAR_TO_ANSI(*Window->GetName()), false, ImGuiSelectableFlags_SpanAvailWidth);
{
Window->SetIsWidgetVisible(Visible);
}
if (ImGui::IsItemHovered())
{
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
}
if (ImGui::IsItemActive() && ImGui::IsItemHovered() == false)
{
const int iNext = i + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
if (iNext >= 0 && iNext < Widgets.Num())
{
Widgets[i] = Widgets[iNext];
Widgets[iNext] = Window;
ImGui::ResetMouseDragDelta();
}
}
ImGui::PopID();
}
}
ImGui::EndChild();
}
//-------------------------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Shortcuts", ImGuiTreeNodeFlags_DefaultOpen))
{
@@ -38,10 +38,7 @@ public:
virtual void GameTick(float DeltaTime);
/** */
virtual float GetMainMenuWidgetWidth(int32 SubWidgetIndex, float MaxWidth) { return -1.0f; }
/** */
virtual void RenderMainMenuWidget(int32 SubWidgetIndex, float Width) {}
virtual void RenderMainMenuWidget() {}
ImGuiID GetID() const { return ID; }
@@ -61,7 +58,7 @@ public:
void SetIsVisible(bool Value);
bool HasWidget() const { return bHasWidget; }
int32 HasWidget() const { return bHasWidget; }
bool GetIsWidgetVisible() const { return bIsWidgetVisible; }
@@ -107,6 +104,8 @@ protected:
virtual void OnSelectionChanged(AActor* OldSelection, AActor* NewSelection) {}
virtual bool IsWindowRenderedInMainMenu();
APawn* GetLocalPlayerPawn() const;
APlayerController* GetLocalPlayerController() const;
@@ -123,7 +122,7 @@ protected:
bool bIsVisible = false;
bool bHasWidget = false;
int32 bHasWidget = 0;
bool bIsWidgetVisible = false;
@@ -75,12 +75,15 @@ public:
FCogImguiContext& GetContext() { return Context; }
static void AddCommand(UPlayerInput* PlayerInput, const FString& Command, const FKey& Key);
static void SortCommands(UPlayerInput* PlayerInput);
void OnShortcutsDefined() const;
bool IsRenderingMainMenu() const { return IsRenderingInMainMenu; }
protected:
friend class FCogWindow_Layouts;
@@ -111,6 +114,8 @@ protected:
virtual void HandleInputs();
virtual void RenderWidgets();
static void SettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*);
static void SettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*);
@@ -169,6 +174,8 @@ protected:
bool bIsSelectionModeActive = false;
bool IsInitialized = false;
bool IsRenderingInMainMenu = false;
};
//--------------------------------------------------------------------------------------------------------------------------
@@ -27,7 +27,7 @@ public:
static void EndTableTooltip();
static void ItemTooltipWrappedText(const char* InText);
static bool ItemTooltipWrappedText(const char* InText);
static bool BeginItemTableTooltip();
@@ -61,7 +61,7 @@ public:
static void AddTextWithShadow(ImDrawList* DrawList, const ImVec2& Position, ImU32 Color, const char* TextBegin, const char* TextEnd = NULL);
static void SearchBar(ImGuiTextFilter& Filter, float Width = -1.0f);
static bool SearchBar(const char* InLabel, ImGuiTextFilter& InFilter, float InWidth = -1.0f);
static void PushBackColor(const ImVec4& Color);
@@ -90,7 +90,7 @@ public:
static bool InputKey(const char* Label, FCogImGuiKeyInfo& KeyInfo);
static bool InputKey(FCogImGuiKeyInfo& KeyInfo);
static bool KeyBind(FKeyBind& KeyBind);
static bool ButtonWithTooltip(const char* Text, const char* Tooltip);
@@ -117,7 +117,9 @@ public:
static void SmallButton(const char* Text, const ImVec4& Color);
static bool InputText(const char* Text, FString& Value);
static bool InputText(const char* Text, FString& Value, ImGuiInputTextFlags InFlags = 0, ImGuiInputTextCallback InCallback = nullptr, void* InUserData = nullptr);
static bool InputTextWithHint(const char* InText, const char* InHint, FString& InValue, ImGuiInputTextFlags InFlags = 0, ImGuiInputTextCallback InCallback = nullptr, void* InUserData = nullptr);
static bool BeginRightAlign(const char* Id);
@@ -133,6 +135,8 @@ public:
static bool OpenObjectAssetButton(const UObject* InObject, const ImVec2& InSize = ImVec2(0, 0));
static void RenderClosebutton(const ImVec2& InPos);
};
template<typename EnumType>
@@ -37,6 +37,15 @@ protected:
TObjectPtr<UCogWindowConfig_Settings> Config = nullptr;
};
//--------------------------------------------------------------------------------------------------------------------------
UENUM()
enum class ECogWidgetAlignment
{
Left = 0,
Center = 1,
Right = 2,
Manual = 3
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(Config = Cog)
@@ -85,6 +94,12 @@ public:
UPROPERTY(Config)
bool bDisableShortcutsWhenImGuiWantTextInput = false;
UPROPERTY(Config)
ECogWidgetAlignment WidgetAlignment = ECogWidgetAlignment::Right;
UPROPERTY(Config)
bool ShowWidgetBorders = false;
UPROPERTY(Config)
FCogImGuiKeyInfo ToggleImGuiInputShortcut = FCogImGuiKeyInfo(EKeys::F1);
+17 -5
View File
@@ -8757,21 +8757,33 @@ bool ImGui::BeginMainMenuBar()
bool is_open = BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags);
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
if (is_open)
BeginMenuBar();
else
if (!is_open)
{
End();
return false;
}
// Temporarily disable _NoSavedSettings, in the off-chance that tables or child windows submitted within the menu-bar may want to use settings. (#8356)
g.CurrentWindow->Flags &= ~ImGuiWindowFlags_NoSavedSettings;
BeginMenuBar();
return is_open;
}
void ImGui::EndMainMenuBar()
{
ImGuiContext& g = *GImGui;
if (!g.CurrentWindow->DC.MenuBarAppending)
{
IM_ASSERT_USER_ERROR(0, "Calling EndMainMenuBar() not from a menu-bar!"); // Not technically testing that it is the main menu bar
return;
}
EndMenuBar();
g.CurrentWindow->Flags |= ImGuiWindowFlags_NoSavedSettings; // Restore _NoSavedSettings (#8356)
// When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window
// FIXME: With this strategy we won't be able to restore a NULL focus.
ImGuiContext& g = *GImGui;
if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest)
if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest && g.ActiveId == 0)
FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild);
End();
@@ -140,7 +140,7 @@ void FCogAIWindow_BehaviorTree::RenderContent()
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -46,7 +46,7 @@ void FCogAIWindow_Blackboard::RenderContent()
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -175,7 +175,7 @@ void FCogAbilityWindow_Abilities::RenderAbilitiesMenu(AActor* Selection)
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -108,7 +108,7 @@ void FCogAbilityWindow_Attributes::RenderContent()
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -280,7 +280,7 @@ void FCogAbilityWindow_Attributes::RenderContent()
{
Selected = Index;
if (ImGui::IsMouseDoubleClicked(0))
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
OpenAttributeDetails(Attribute);
}
@@ -22,29 +22,6 @@ void FCogAbilityWindow_Cheats::Initialize()
Asset = GetAsset<UCogAbilityDataAsset>();
Config = GetConfig<UCogAbilityConfig_Cheats>();
AlignmentConfig = GetConfig<UCogAbilityConfig_Alignment>();
FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
TEXT("Cog.Cheat"),
TEXT("Apply a cheat to the selection. Cog.Cheat <CheatName> -Allies -Enemies -Controlled"),
GetWorld(),
FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
if (InArgs.Num() > 0)
{
if (const FCogAbilityCheat* cheat = FindCheatByName(InArgs[0]))
{
const bool ApplyToEnemies = InArgs.Contains("-Enemies");
const bool ApplyToAllies = InArgs.Contains("-Allies");
const bool ApplyToControlled = InArgs.Contains("-Controlled");
RequestCheat(GetLocalPlayerPawn(), GetSelection(), *cheat, ApplyToEnemies, ApplyToAllies, ApplyToControlled);
}
else
{
UE_LOG(LogCogImGui, Warning, TEXT("Cog.Cheat %s | Cheat not found"), *InArgs[0]);
}
}
}));
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -74,7 +74,7 @@ void FCogAbilityWindow_Effects::RenderContent()
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -67,7 +67,7 @@ void FCogAbilityWindow_Tags::RenderMenu()
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}
@@ -98,7 +98,7 @@ void FCogAbilityWindow_Tasks::RenderTaskMenu(AActor* Selection)
ImGui::EndMenu();
}
FCogWindowWidgets::SearchBar(Filter);
FCogWindowWidgets::SearchBar("##Filter", Filter);
ImGui::EndMenuBar();
}