Skip to content

Commit 779a205

Browse files
committed
Added a GUI test.
1 parent 48074eb commit 779a205

File tree

9 files changed

+332
-3
lines changed

9 files changed

+332
-3
lines changed

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
[submodule "wiki"]
55
path = wiki
66
url = https://github.com/ZCG-coder/Steppable.wiki.git
7+
[submodule "include/imgui"]
8+
path = include/imgui
9+
url = https://github.com/ZCG-coder/imgui.git
10+
branch = docking

CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ SET(COMPONENTS
101101
division
102102
root
103103
factorial
104-
trig hyp log)
104+
trig
105+
hyp
106+
log)
105107
# NEW_COMPONENT: PATCH Do NOT remove the previous comment.
106108

107109
SET(TARGETS ${COMPONENTS} util)
@@ -117,6 +119,7 @@ ENDFOREACH()
117119
ADD_SUBDIRECTORY(src/)
118120
ADD_SUBDIRECTORY(lib/)
119121
ADD_SUBDIRECTORY(tests/)
122+
ADD_SUBDIRECTORY(gui/)
120123
ADD_SUBDIRECTORY(include/) # The CMakeLists file there adds the include/ directory to everything
121124

122125
FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)

gui/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
FUNCTION(ADD_GUI SOURCE)
2+
GET_FILENAME_COMPONENT(NAME ${SOURCE} NAME_WE)
3+
SET(NAME "gui_${NAME}")
4+
5+
ADD_EXECUTABLE(${NAME} ${SOURCE})
6+
TARGET_LINK_LIBRARIES(${NAME} PRIVATE ${SDL2_LIBRARIES} ${OPENGL_LIBRARIES})
7+
TARGET_LINK_LIBRARIES(${NAME} PRIVATE imgui)
8+
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
9+
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE "${STP_BASE_DIRECTORY}/include/imgui")
10+
11+
# Link Steppable stuff
12+
TARGET_LINK_LIBRARIES(${NAME} PRIVATE calc util)
13+
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE ${STP_BASE_DIRECTORY}/include)
14+
15+
if(FREETYPE_FOUND)
16+
TARGET_LINK_LIBRARIES(${NAME} PRIVATE ${FREETYPE_LIBRARIES})
17+
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE ${FREETYPE_INCLUDE_DIRS})
18+
TARGET_COMPILE_DEFINITIONS(${NAME} PRIVATE IMGUI_ENABLE_FREETYPE)
19+
TARGET_LINK_LIBRARIES(${NAME} PRIVATE imgui_freetype)
20+
endif()
21+
ENDFUNCTION()
22+
23+
IF (STP_BUILD_GUI EQUAL 1)
24+
# Find and link SDL2 and OpenGL
25+
FIND_PACKAGE(SDL2 REQUIRED)
26+
FIND_PACKAGE(OpenGL REQUIRED)
27+
ADD_GUI(test.cpp)
28+
ENDIF()

gui/test.cpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#include "backends/imgui_impl_opengl3.h"
2+
#include "backends/imgui_impl_sdl2.h"
3+
#include "gui.hpp"
4+
#include "imgui.h"
5+
#include "output.hpp"
6+
7+
#include <SDL.h>
8+
#include <SDL_opengl.h>
9+
#include <array>
10+
11+
using namespace steppable;
12+
using namespace steppable::gui::__internals;
13+
14+
int main()
15+
{
16+
// Setup SDL
17+
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
18+
{
19+
steppable::output::error("Error: {0}\n", std::string(SDL_GetError()));
20+
return -1;
21+
}
22+
23+
// Decide GL+GLSL versions
24+
#if defined(IMGUI_IMPL_OPENGL_ES2)
25+
// GL ES 2.0 + GLSL 100
26+
const char* glsl_version = "#version 100";
27+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
28+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
29+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
30+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
31+
#elif defined(__APPLE__)
32+
// GL 3.2 Core + GLSL 150
33+
const char* glsl_version = "#version 150";
34+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
35+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
36+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
37+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
38+
#else
39+
// GL 3.0 + GLSL 130
40+
const char* glsl_version = "#version 130";
41+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
42+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
43+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
44+
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
45+
#endif
46+
47+
// From 2.0.18: Enable native IME.
48+
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
49+
50+
// Create window with graphics context
51+
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
52+
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
53+
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
54+
auto window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
55+
SDL_Window* window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
56+
if (window == nullptr)
57+
{
58+
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
59+
return -1;
60+
}
61+
62+
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
63+
SDL_GL_MakeCurrent(window, gl_context);
64+
SDL_GL_SetSwapInterval(1); // Enable vsync
65+
66+
// Setup Dear ImGui context
67+
IMGUI_CHECKVERSION();
68+
ImGui::CreateContext();
69+
ImGuiIO& io = ImGui::GetIO();
70+
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
71+
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
72+
73+
// Setup Dear ImGui style
74+
ImGui::StyleColorsDark();
75+
// ImGui::StyleColorsLight();
76+
77+
// Setup Platform/Renderer backends
78+
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
79+
ImGui_ImplOpenGL3_Init(glsl_version);
80+
81+
bool done = false;
82+
ImVec4 clear_color = ImVec4(0.45, 0.55, 0.60, 1.00);
83+
std::array<char, 100> buf{};
84+
loadFonts(&io);
85+
86+
while (not done)
87+
{
88+
// Poll and handle events (inputs, window resize, etc.)
89+
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your
90+
// inputs.
91+
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or
92+
// clear/overwrite your copy of the mouse data.
93+
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or
94+
// clear/overwrite your copy of the keyboard data. Generally you may always pass all inputs to dear imgui, and
95+
// hide them from your application based on those two flags.
96+
SDL_Event event;
97+
while (SDL_PollEvent(&event) != 0)
98+
{
99+
ImGui_ImplSDL2_ProcessEvent(&event);
100+
if (event.type == SDL_QUIT)
101+
done = true;
102+
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE &&
103+
event.window.windowID == SDL_GetWindowID(window))
104+
done = true;
105+
}
106+
107+
// Start the Dear ImGui frame
108+
ImGui_ImplOpenGL3_NewFrame();
109+
ImGui_ImplSDL2_NewFrame();
110+
ImGui::NewFrame();
111+
112+
ImGui::Begin("My Window");
113+
ImGui::Text("Testing!");
114+
ImGui::InputText("Input", buf.data(), buf.size());
115+
ImGui::End();
116+
117+
// Rendering
118+
ImGui::Render();
119+
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
120+
glClearColor(
121+
clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
122+
glClear(GL_COLOR_BUFFER_BIT);
123+
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
124+
SDL_GL_SwapWindow(window);
125+
}
126+
127+
// Cleanup
128+
ImGui_ImplOpenGL3_Shutdown();
129+
ImGui_ImplSDL2_Shutdown();
130+
ImGui::DestroyContext();
131+
132+
SDL_GL_DeleteContext(gl_context);
133+
SDL_DestroyWindow(window);
134+
SDL_Quit();
135+
136+
return 0;
137+
}

include/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,31 @@
2424
FOREACH(TARGET IN LISTS TEST_TARGETS)
2525
TARGET_INCLUDE_DIRECTORIES(${TARGET} PUBLIC ${STP_BASE_DIRECTORY}/include/)
2626
ENDFOREACH(TARGET)
27+
28+
IF (STP_BUILD_GUI EQUAL 1)
29+
FIND_PACKAGE(SDL2 REQUIRED)
30+
ADD_LIBRARY(imgui
31+
imgui/imgui.cpp
32+
imgui/imgui_draw.cpp
33+
imgui/imgui_widgets.cpp
34+
imgui/imgui_tables.cpp
35+
imgui/imgui_demo.cpp
36+
imgui/backends/imgui_impl_sdl2.cpp
37+
imgui/backends/imgui_impl_opengl3.cpp)
38+
39+
# If we have freetype, we can use it to render text
40+
FIND_PACKAGE(Freetype QUIET)
41+
if (FREETYPE_FOUND)
42+
MESSAGE(STATUS "Found Freetype")
43+
ADD_LIBRARY(imgui_freetype STATIC "${STP_BASE_DIRECTORY}/include/imgui/misc/freetype/imgui_freetype.cpp")
44+
TARGET_INCLUDE_DIRECTORIES(imgui_freetype PRIVATE "${STP_BASE_DIRECTORY}/include/imgui")
45+
TARGET_LINK_LIBRARIES(imgui_freetype PRIVATE ${FREETYPE_LIBRARIES})
46+
TARGET_LINK_LIBRARIES(imgui PRIVATE imgui_freetype)
47+
TARGET_INCLUDE_DIRECTORIES(imgui_freetype PRIVATE ${FREETYPE_INCLUDE_DIRS})
48+
TARGET_COMPILE_DEFINITIONS(imgui PRIVATE IMGUI_ENABLE_FREETYPE)
49+
endif()
50+
51+
TARGET_LINK_LIBRARIES(imgui PRIVATE SDL2::SDL2)
52+
TARGET_INCLUDE_DIRECTORIES(imgui PRIVATE ${SDL2_INCLUDE_DIRS})
53+
TARGET_INCLUDE_DIRECTORIES(imgui PRIVATE "${STP_BASE_DIRECTORY}/include/imgui")
54+
ENDIF()

include/gui.hpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#pragma once
2+
3+
#include "output.hpp"
4+
5+
#include <backends/imgui_impl_opengl3.h>
6+
#include <backends/imgui_impl_sdl2.h>
7+
#include <filesystem>
8+
#include <imgui.h>
9+
#include <string>
10+
11+
using namespace std::literals;
12+
13+
namespace steppable::gui::__internals
14+
{
15+
inline void addIfExistent(const ImGuiIO* io,
16+
const std::filesystem::path& path,
17+
const ImFontConfig* config,
18+
const ImWchar* ranges) noexcept
19+
{
20+
if (io->Fonts->Fonts.empty() and config->MergeMode)
21+
config = nullptr;
22+
if (std::filesystem::exists(path))
23+
{
24+
#ifdef DEBUG
25+
output::info("addIfExistent"s, "Added font {0}"s, { path });
26+
#endif
27+
io->Fonts->AddFontFromFileTTF(path.c_str(), 15.0F, config, ranges);
28+
}
29+
}
30+
31+
inline void loadFonts(const ImGuiIO* io) noexcept
32+
{
33+
ImFontConfig config;
34+
config.MergeMode = true;
35+
#ifdef WINDOWS
36+
// WINDOWS fonts
37+
// -------------
38+
// Chinese -> Microsoft YaHei
39+
// Cyrillic -> Segoe UI -----------------+
40+
// Greek -> Segoe UI -----------------|
41+
// Japanese -> Meiryo |
42+
// Korean -> Malgun Gothic +--> Top-priority
43+
// Thai -> Leelawadee |
44+
// Vietnamese -> Segoe UI -----------------+
45+
46+
// Load top-priority fonts
47+
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesCyrillic());
48+
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesDefault());
49+
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesGreek());
50+
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesVietnamese());
51+
52+
// Load Chinese fonts
53+
addIfExistent(io, "C:/Windows/Fonts/msyh.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());
54+
55+
// Load Japanese fonts
56+
addIfExistent(io, "C:/Windows/Fonts/meiryo.ttc", &config, io->Fonts->GetGlyphRangesJapanese());
57+
58+
// Load Korean fonts
59+
addIfExistent(io, "C:/Windows/Fonts/malgun.ttf", &config, io->Fonts->GetGlyphRangesKorean());
60+
61+
// Load Thai fonts
62+
addIfExistent(io, "C:/Windows/Fonts/leelawad.ttf", &config, io->Fonts->GetGlyphRangesThai());
63+
#elif defined(MACOSX)
64+
// MACOS fonts
65+
// -------------
66+
// Chinese -> PingFang SC (*)
67+
// Cyrillic -> SF Pro -----------------+
68+
// Greek -> SF Pro -----------------|
69+
// Japanese -> Hiragino Sans |
70+
// Korean -> Apple SD Gothic Neo +--> Top-priority
71+
// Thai -> Thonburi |
72+
// Vietnamese -> SF Pro -----------------+
73+
//
74+
// (*) NOTE: PingFang may not be available on all systems, but STHeiti Medium is a good alternative.
75+
76+
// Load top-priority fonts
77+
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesCyrillic());
78+
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesDefault());
79+
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesGreek());
80+
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesVietnamese());
81+
82+
// Load Chinese fonts
83+
addIfExistent(io, "/System/Library/Fonts/PingFang.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());
84+
addIfExistent(io, "/System/Library/Fonts/STHeiti Medium.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());
85+
86+
// Load Japanese fonts
87+
addIfExistent(io, "/System/Library/Fonts/Hiragino.ttc", &config, io->Fonts->GetGlyphRangesJapanese());
88+
89+
// Load Korean fonts
90+
addIfExistent(io, "/System/Library/Fonts/AppleSDGothicNeo.ttc", &config, io->Fonts->GetGlyphRangesKorean());
91+
92+
// Load Thai fonts
93+
addIfExistent(io, "/System/Library/Fonts/Thonburi.ttf", &config, io->Fonts->GetGlyphRangesThai());
94+
addIfExistent(io, "/System/Library/Fonts/Supplemental/Ayuthaya.ttf", &config, io->Fonts->GetGlyphRangesThai());
95+
#elif defined(LINUX)
96+
// LINUX fonts
97+
// -------------
98+
// Chinese -> WenQuanYi Zen Hei
99+
// Cyrillic -> DejaVu Sans -----------------+
100+
// Greek -> DejaVu Sans -----------------|
101+
// Japanese -> Takao Gothic |
102+
// Korean -> Nanum Gothic +--> Top-priority
103+
// Thai -> Garuda |
104+
// Vietnamese -> DejaVu Sans -----------------+
105+
106+
// Load top-priority fonts
107+
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesCyrillic());
108+
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesDefault());
109+
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesGreek());
110+
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesVietnamese());
111+
112+
// Load Chinese fonts
113+
addIfExistent(io, "/usr/share/fonts/TTF/wqy-zenhei.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());
114+
115+
// Load Japanese fonts
116+
addIfExistent(io, "/usr/share/fonts/TTF/takao-mincho.ttf", &config, io->Fonts->GetGlyphRangesJapanese());
117+
118+
// Load Korean fonts
119+
addIfExistent(io, "/usr/share/fonts/TTF/NanumGothic.ttf", &config, io->Fonts->GetGlyphRangesKorean());
120+
121+
// Load Thai fonts
122+
addIfExistent(io, "/usr/share/fonts/TTF/garuda.ttf", &config, io->Fonts->GetGlyphRangesThai());
123+
#endif
124+
// Add the default font as well.
125+
io->Fonts->AddFontDefault(&config);
126+
io->Fonts->Build();
127+
}
128+
} // namespace steppable::gui::__internals

include/imgui

Submodule imgui added at 469dfd1

wiki

Submodule wiki updated from b7b1301 to 3cde4c9

0 commit comments

Comments
 (0)