Skip to content

Commit 5f47b2c

Browse files
committed
gh-89: implement ui elements in imgui backend
1 parent 14e8412 commit 5f47b2c

39 files changed

+2228
-1206
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ jobs:
7878
- name: Install glew dependencies
7979
shell: bash
8080
run: |
81-
sudo apt-get install -y libgl1-mesa-dri libgl1-mesa-glx libgl1-mesa-dev
81+
sudo apt-get install -y libgl1-mesa-dri libgl1 libglx-mesa0 libgl1-mesa-dev
8282
sudo apt-get install -y libxmu-dev libxi-dev libgl-dev libglx-dev
8383
sudo apt-get install -y libx11-dev
8484
8585
- name: Install openal dependencies
8686
shell: bash
8787
run: |
88-
sudo apt-get install -y libpulse-dev portaudio19-dev libasound2-dev libjack-dev libpipewire-0.2-dev qtbase5-dev libdbus-1-dev
88+
sudo apt-get install -y libpulse-dev portaudio19-dev libasound2-dev libjack-dev qtbase5-dev libdbus-1-dev
8989
9090
- name: Install Vulkan SDK
9191
uses: humbletim/setup-vulkan-sdk@v1.2.1

deps/imgui/imgui.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ namespace ImGui
576576
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified.
577577
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0));
578578
IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
579+
IMGUI_API bool ImageButtonWithLabel(const char* str_id, const char* label, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
579580

580581
// Widgets: Combo Box (Dropdown)
581582
// - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items.

deps/imgui/imgui_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3703,6 +3703,7 @@ namespace ImGui
37033703
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
37043704
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
37053705
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
3706+
IMGUI_API bool ImageButtonWithLabelEx(ImGuiID id, const char* label, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
37063707
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
37073708
IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
37083709
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);

deps/imgui/imgui_widgets.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,49 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2&
11111111
return pressed;
11121112
}
11131113

1114+
bool ImGui::ImageButtonWithLabelEx(ImGuiID id, const char* label, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
1115+
{
1116+
ImGuiContext& g = *GImGui;
1117+
const ImGuiStyle& style = g.Style;
1118+
ImGuiWindow* window = GetCurrentWindow();
1119+
if (window->SkipItems)
1120+
return false;
1121+
1122+
const ImVec2 padding = g.Style.FramePadding;
1123+
const ImVec2 label_size = CalcTextSize(label, NULL, true);
1124+
const float label_padding = label_size.x > 0 ? style.ItemInnerSpacing.x : 0.0f;
1125+
const ImVec2 bb_size = ImVec2(
1126+
image_size.x + label_padding + label_size.x + padding.x * 2.0f,
1127+
ImMax(image_size.y, label_size.y) + padding.y * 2.0f);
1128+
1129+
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + bb_size);
1130+
ItemSize(bb);
1131+
if (!ItemAdd(bb, id))
1132+
return false;
1133+
1134+
bool hovered, held;
1135+
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
1136+
1137+
const ImRect bb_image(
1138+
bb.Min + ImVec2(padding.x, (bb_size.y - image_size.y) * 0.5f),
1139+
bb.Min + ImVec2(padding.x + image_size.x, (bb_size.y - image_size.y) * 0.5f + image_size.y));
1140+
1141+
const ImRect bb_text(
1142+
bb.Min + ImVec2(padding.x + image_size.x + label_padding, (bb_size.y - label_size.y) * 0.5f),
1143+
bb.Min + ImVec2(padding.x + image_size.x + label_padding + label_size.x, (bb_size.y - label_size.y) * 0.5f + label_size.y));
1144+
1145+
// Render
1146+
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
1147+
RenderNavCursor(bb, id);
1148+
RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
1149+
if (bg_col.w > 0.0f)
1150+
window->DrawList->AddRectFilled(bb_image.Min, bb_image.Max, GetColorU32(bg_col));
1151+
window->DrawList->AddImage(user_texture_id, bb_image.Min, bb_image.Max, uv0, uv1, GetColorU32(tint_col));
1152+
RenderTextClipped(bb_text.Min, bb_text.Max, label, NULL, &label_size, style.ButtonTextAlign, &bb);
1153+
1154+
return pressed;
1155+
}
1156+
11141157
// - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button.
11151158
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design?
11161159
bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
@@ -1123,6 +1166,16 @@ bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const I
11231166
return ImageButtonEx(window->GetID(str_id), user_texture_id, image_size, uv0, uv1, bg_col, tint_col);
11241167
}
11251168

1169+
bool ImGui::ImageButtonWithLabel(const char* str_id, const char* label, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
1170+
{
1171+
ImGuiContext& g = *GImGui;
1172+
ImGuiWindow* window = g.CurrentWindow;
1173+
if (window->SkipItems)
1174+
return false;
1175+
1176+
return ImageButtonWithLabelEx(window->GetID(str_id), label, user_texture_id, image_size, uv0, uv1, bg_col, tint_col);
1177+
}
1178+
11261179
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
11271180
// Legacy API obsoleted in 1.89. Two differences with new ImageButton()
11281181
// - old ImageButton() used ImTextureID as item id (created issue with multiple buttons with same image, transient texture id values, opaque computation of ID)

editor/code/window/edt_main_window.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#pragma once
2929

3030
#include "platform/window.hpp"
31-
#include "ui/ui_elements.hpp"
3231

3332
namespace wmoge {
3433

@@ -37,8 +36,7 @@ namespace wmoge {
3736
EdtMainWindow(Ref<Window> window);
3837

3938
private:
40-
Ref<UiMainWindow> m_ui_window;
41-
Ref<Window> m_window;
39+
Ref<Window> m_window;
4240
};
4341

4442
}// namespace wmoge

engine/code/engine.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,16 @@
227227
#include "system/plugin.hpp"
228228
#include "system/plugin_manager.hpp"
229229

230+
#include "ui/ui_bars.hpp"
231+
#include "ui/ui_containers.hpp"
232+
#include "ui/ui_content.hpp"
233+
#include "ui/ui_controls.hpp"
230234
#include "ui/ui_defs.hpp"
231235
#include "ui/ui_element.hpp"
232-
#include "ui/ui_elements.hpp"
233-
#include "ui/ui_factory.hpp"
236+
#include "ui/ui_inputs.hpp"
234237
#include "ui/ui_manager.hpp"
235238
#include "ui/ui_style.hpp"
239+
#include "ui/ui_views.hpp"
240+
#include "ui/ui_window.hpp"
236241

237242
#include "game/game_manager.hpp"

engine/code/ui/ui_attribute.hpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,24 @@ namespace wmoge {
4141
UiAttribute() = default;
4242
UiAttribute(T value) : m_value(std::move(value)) {}
4343

44-
void set(T value) { m_value = std::move(value); }
45-
const T& get() const { return m_value; }
44+
UiAttribute& operator=(const T& value) {
45+
m_value = value;
46+
return *this;
47+
}
48+
49+
UiAttribute& operator=(T&& value) {
50+
m_value = std::move(value);
51+
return *this;
52+
}
53+
54+
void set(T value) { m_value = std::move(value); }
55+
56+
operator T() const { return m_value; }
57+
58+
[[nodiscard]] const T& get() const { return m_value; }
59+
[[nodiscard]] T& get() { return m_value; }
60+
[[nodiscard]] const T* get_ptr() const { return &m_value; }
61+
[[nodiscard]] T* get_ptr() { return &m_value; }
4662

4763
protected:
4864
T m_value;
@@ -51,32 +67,46 @@ namespace wmoge {
5167
template<typename T>
5268
class UiAttributeList : public UiAttribute<std::vector<T>> {
5369
public:
70+
using UiAttribute<std::vector<T>>::m_value;
71+
5472
void add_element(T element) { m_value.push_back(std::move(element)); }
5573
};
5674

5775
template<typename T>
5876
class UiAttributeOpt : public UiAttribute<std::optional<T>> {
5977
public:
78+
using UiAttribute<std::optional<T>>::m_value;
79+
using UiAttribute<std::optional<T>>::operator=;
80+
6081
bool has_value() const { return m_value.has_value(); }
6182
const T& value() const { return m_value.value(); }
83+
void reset() { m_value.reset(); }
6284
};
6385

6486
template<typename T>
6587
class UiEvent : public UiAttribute<T> {
6688
public:
67-
void has_callback() const { return m_value; }
89+
using UiAttribute<T>::m_value;
90+
using UiAttribute<T>::operator=;
91+
92+
bool has_callback() const { return (bool) m_value; }
6893
};
6994

7095
template<typename T>
7196
class UiSlot : public UiAttribute<Ref<T>> {
7297
public:
98+
using UiAttribute<Ref<T>>::m_value;
99+
using UiAttribute<Ref<T>>::operator=;
100+
73101
bool has_value() const { return m_value; }
74102
};
75103

76104
template<typename T>
77105
class UiSlots : public UiAttribute<std::vector<T>> {
78106
public:
79-
T& add_slot() { m_value.emplace_back(); }
107+
using UiAttribute<std::vector<T>>::m_value;
108+
109+
T& add_slot() { return m_value.emplace_back(); }
80110
array_view<const T> get_slots() const { return m_value; }
81111
};
82112

engine/plugins/imgui/code/imgui_element.hpp renamed to engine/code/ui/ui_bars.hpp

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,51 +27,48 @@
2727

2828
#pragma once
2929

30-
#include <functional>
30+
#include "ui/ui_attribute.hpp"
31+
#include "ui/ui_element.hpp"
3132

3233
namespace wmoge {
3334

34-
class ImguiManager;
35-
3635
/**
37-
* @class ImguiProcessContext
38-
* @brief Context for imgui 'draw' ui elements pass
36+
* @class UiMenuBar
37+
* @brief
3938
*/
40-
class ImguiProcessContext {
39+
class UiMenuBar : public UiElement {
4140
public:
42-
ImguiProcessContext() = default;
41+
UiMenuBar() : UiElement(UiElementType::MenuBar) {}
4342

44-
void add_action(std::function<void()> action);
45-
void exec_actions();
43+
using Slot = UiSlot<UiSubElement>;
4644

47-
private:
48-
std::vector<std::function<void()>> m_actions;
45+
UiSlots<Slot> children;
4946
};
5047

5148
/**
52-
* @class ImguiElement
53-
* @brief Base class for all imgui backend ui elements
49+
* @class UiToolBar
50+
* @brief
5451
*/
55-
class ImguiElement {
52+
class UiToolBar : public UiElement {
5653
public:
57-
ImguiElement(ImguiManager* manager);
58-
virtual ~ImguiElement() = default;
54+
UiToolBar() : UiElement(UiElementType::ToolBar) {}
5955

60-
virtual void process(ImguiProcessContext& context) {}
56+
using Slot = UiSlot<UiSubElement>;
6157

62-
protected:
63-
ImguiManager* m_manager;
58+
UiSlots<Slot> children;
6459
};
6560

6661
/**
67-
* @class ImguiElementBase
68-
* @brief Helper class to implement ui element
62+
* @class UiStatusBar
63+
* @brief
6964
*/
70-
template<typename UiBaseClass>
71-
class ImguiElementBase : public UiBaseClass, public ImguiElement {
65+
class UiStatusBar : public UiElement {
7266
public:
73-
ImguiElementBase(ImguiManager* manager) : ImguiElement(manager) {}
74-
~ImguiElementBase() override = default;
67+
UiStatusBar() : UiElement(UiElementType::StatusBar) {}
68+
69+
using Slot = UiSlot<UiSubElement>;
70+
71+
UiSlots<Slot> children;
7572
};
7673

7774
}// namespace wmoge

0 commit comments

Comments
 (0)