Skip to content

Commit

Permalink
Added a GUI test.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZCG-coder committed Jul 15, 2024
1 parent 48074eb commit 779a205
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 3 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
[submodule "wiki"]
path = wiki
url = https://github.com/ZCG-coder/Steppable.wiki.git
[submodule "include/imgui"]
path = include/imgui
url = https://github.com/ZCG-coder/imgui.git
branch = docking
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ SET(COMPONENTS
division
root
factorial
trig hyp log)
trig
hyp
log)
# NEW_COMPONENT: PATCH Do NOT remove the previous comment.

SET(TARGETS ${COMPONENTS} util)
Expand All @@ -117,6 +119,7 @@ ENDFOREACH()
ADD_SUBDIRECTORY(src/)
ADD_SUBDIRECTORY(lib/)
ADD_SUBDIRECTORY(tests/)
ADD_SUBDIRECTORY(gui/)
ADD_SUBDIRECTORY(include/) # The CMakeLists file there adds the include/ directory to everything

FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
Expand Down
2 changes: 1 addition & 1 deletion doxygen-awesome-css
28 changes: 28 additions & 0 deletions gui/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FUNCTION(ADD_GUI SOURCE)
GET_FILENAME_COMPONENT(NAME ${SOURCE} NAME_WE)
SET(NAME "gui_${NAME}")

ADD_EXECUTABLE(${NAME} ${SOURCE})
TARGET_LINK_LIBRARIES(${NAME} PRIVATE ${SDL2_LIBRARIES} ${OPENGL_LIBRARIES})
TARGET_LINK_LIBRARIES(${NAME} PRIVATE imgui)
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE "${STP_BASE_DIRECTORY}/include/imgui")

# Link Steppable stuff
TARGET_LINK_LIBRARIES(${NAME} PRIVATE calc util)
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE ${STP_BASE_DIRECTORY}/include)

if(FREETYPE_FOUND)
TARGET_LINK_LIBRARIES(${NAME} PRIVATE ${FREETYPE_LIBRARIES})
TARGET_INCLUDE_DIRECTORIES(${NAME} PRIVATE ${FREETYPE_INCLUDE_DIRS})
TARGET_COMPILE_DEFINITIONS(${NAME} PRIVATE IMGUI_ENABLE_FREETYPE)
TARGET_LINK_LIBRARIES(${NAME} PRIVATE imgui_freetype)
endif()
ENDFUNCTION()

IF (STP_BUILD_GUI EQUAL 1)
# Find and link SDL2 and OpenGL
FIND_PACKAGE(SDL2 REQUIRED)
FIND_PACKAGE(OpenGL REQUIRED)
ADD_GUI(test.cpp)
ENDIF()
137 changes: 137 additions & 0 deletions gui/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include "backends/imgui_impl_opengl3.h"
#include "backends/imgui_impl_sdl2.h"
#include "gui.hpp"
#include "imgui.h"
#include "output.hpp"

#include <SDL.h>
#include <SDL_opengl.h>
#include <array>

using namespace steppable;
using namespace steppable::gui::__internals;

int main()
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
steppable::output::error("Error: {0}\n", std::string(SDL_GetError()));
return -1;
}

// Decide GL+GLSL versions
#if defined(IMGUI_IMPL_OPENGL_ES2)
// GL ES 2.0 + GLSL 100
const char* glsl_version = "#version 100";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#elif defined(__APPLE__)
// GL 3.2 Core + GLSL 150
const char* glsl_version = "#version 150";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
#else
// GL 3.0 + GLSL 130
const char* glsl_version = "#version 130";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif

// From 2.0.18: Enable native IME.
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");

// Create window with graphics context
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
auto window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}

SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync

// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;

// Setup Dear ImGui style
ImGui::StyleColorsDark();
// ImGui::StyleColorsLight();

// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init(glsl_version);

bool done = false;
ImVec4 clear_color = ImVec4(0.45, 0.55, 0.60, 1.00);
std::array<char, 100> buf{};
loadFonts(&io);

while (not done)
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your
// inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or
// clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or
// clear/overwrite your copy of the keyboard data. Generally you may always pass all inputs to dear imgui, and
// hide them from your application based on those two flags.
SDL_Event event;
while (SDL_PollEvent(&event) != 0)
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE &&
event.window.windowID == SDL_GetWindowID(window))
done = true;
}

// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();

ImGui::Begin("My Window");
ImGui::Text("Testing!");
ImGui::InputText("Input", buf.data(), buf.size());
ImGui::End();

// Rendering
ImGui::Render();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(
clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window);
}

// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();

SDL_GL_DeleteContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();

return 0;
}
28 changes: 28 additions & 0 deletions include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,31 @@
FOREACH(TARGET IN LISTS TEST_TARGETS)
TARGET_INCLUDE_DIRECTORIES(${TARGET} PUBLIC ${STP_BASE_DIRECTORY}/include/)
ENDFOREACH(TARGET)

IF (STP_BUILD_GUI EQUAL 1)
FIND_PACKAGE(SDL2 REQUIRED)
ADD_LIBRARY(imgui
imgui/imgui.cpp
imgui/imgui_draw.cpp
imgui/imgui_widgets.cpp
imgui/imgui_tables.cpp
imgui/imgui_demo.cpp
imgui/backends/imgui_impl_sdl2.cpp
imgui/backends/imgui_impl_opengl3.cpp)

# If we have freetype, we can use it to render text
FIND_PACKAGE(Freetype QUIET)
if (FREETYPE_FOUND)
MESSAGE(STATUS "Found Freetype")
ADD_LIBRARY(imgui_freetype STATIC "${STP_BASE_DIRECTORY}/include/imgui/misc/freetype/imgui_freetype.cpp")
TARGET_INCLUDE_DIRECTORIES(imgui_freetype PRIVATE "${STP_BASE_DIRECTORY}/include/imgui")
TARGET_LINK_LIBRARIES(imgui_freetype PRIVATE ${FREETYPE_LIBRARIES})
TARGET_LINK_LIBRARIES(imgui PRIVATE imgui_freetype)
TARGET_INCLUDE_DIRECTORIES(imgui_freetype PRIVATE ${FREETYPE_INCLUDE_DIRS})
TARGET_COMPILE_DEFINITIONS(imgui PRIVATE IMGUI_ENABLE_FREETYPE)
endif()

TARGET_LINK_LIBRARIES(imgui PRIVATE SDL2::SDL2)
TARGET_INCLUDE_DIRECTORIES(imgui PRIVATE ${SDL2_INCLUDE_DIRS})
TARGET_INCLUDE_DIRECTORIES(imgui PRIVATE "${STP_BASE_DIRECTORY}/include/imgui")
ENDIF()
128 changes: 128 additions & 0 deletions include/gui.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#pragma once

#include "output.hpp"

#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_sdl2.h>
#include <filesystem>
#include <imgui.h>
#include <string>

using namespace std::literals;

namespace steppable::gui::__internals
{
inline void addIfExistent(const ImGuiIO* io,
const std::filesystem::path& path,
const ImFontConfig* config,
const ImWchar* ranges) noexcept
{
if (io->Fonts->Fonts.empty() and config->MergeMode)
config = nullptr;
if (std::filesystem::exists(path))
{
#ifdef DEBUG
output::info("addIfExistent"s, "Added font {0}"s, { path });
#endif
io->Fonts->AddFontFromFileTTF(path.c_str(), 15.0F, config, ranges);
}
}

inline void loadFonts(const ImGuiIO* io) noexcept
{
ImFontConfig config;
config.MergeMode = true;
#ifdef WINDOWS
// WINDOWS fonts
// -------------
// Chinese -> Microsoft YaHei
// Cyrillic -> Segoe UI -----------------+
// Greek -> Segoe UI -----------------|
// Japanese -> Meiryo |
// Korean -> Malgun Gothic +--> Top-priority
// Thai -> Leelawadee |
// Vietnamese -> Segoe UI -----------------+

// Load top-priority fonts
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesCyrillic());
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesDefault());
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesGreek());
addIfExistent(io, "C:/Windows/Fonts/segoeui.ttf", &config, io->Fonts->GetGlyphRangesVietnamese());

// Load Chinese fonts
addIfExistent(io, "C:/Windows/Fonts/msyh.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());

// Load Japanese fonts
addIfExistent(io, "C:/Windows/Fonts/meiryo.ttc", &config, io->Fonts->GetGlyphRangesJapanese());

// Load Korean fonts
addIfExistent(io, "C:/Windows/Fonts/malgun.ttf", &config, io->Fonts->GetGlyphRangesKorean());

// Load Thai fonts
addIfExistent(io, "C:/Windows/Fonts/leelawad.ttf", &config, io->Fonts->GetGlyphRangesThai());
#elif defined(MACOSX)
// MACOS fonts
// -------------
// Chinese -> PingFang SC (*)
// Cyrillic -> SF Pro -----------------+
// Greek -> SF Pro -----------------|
// Japanese -> Hiragino Sans |
// Korean -> Apple SD Gothic Neo +--> Top-priority
// Thai -> Thonburi |
// Vietnamese -> SF Pro -----------------+
//
// (*) NOTE: PingFang may not be available on all systems, but STHeiti Medium is a good alternative.

// Load top-priority fonts
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesCyrillic());
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesDefault());
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesGreek());
addIfExistent(io, "/Library/Fonts/SF-Pro.ttf", &config, io->Fonts->GetGlyphRangesVietnamese());

// Load Chinese fonts
addIfExistent(io, "/System/Library/Fonts/PingFang.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());
addIfExistent(io, "/System/Library/Fonts/STHeiti Medium.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());

// Load Japanese fonts
addIfExistent(io, "/System/Library/Fonts/Hiragino.ttc", &config, io->Fonts->GetGlyphRangesJapanese());

// Load Korean fonts
addIfExistent(io, "/System/Library/Fonts/AppleSDGothicNeo.ttc", &config, io->Fonts->GetGlyphRangesKorean());

// Load Thai fonts
addIfExistent(io, "/System/Library/Fonts/Thonburi.ttf", &config, io->Fonts->GetGlyphRangesThai());
addIfExistent(io, "/System/Library/Fonts/Supplemental/Ayuthaya.ttf", &config, io->Fonts->GetGlyphRangesThai());
#elif defined(LINUX)
// LINUX fonts
// -------------
// Chinese -> WenQuanYi Zen Hei
// Cyrillic -> DejaVu Sans -----------------+
// Greek -> DejaVu Sans -----------------|
// Japanese -> Takao Gothic |
// Korean -> Nanum Gothic +--> Top-priority
// Thai -> Garuda |
// Vietnamese -> DejaVu Sans -----------------+

// Load top-priority fonts
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesCyrillic());
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesDefault());
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesGreek());
addIfExistent(io, "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", &config, io->Fonts->GetGlyphRangesVietnamese());

// Load Chinese fonts
addIfExistent(io, "/usr/share/fonts/TTF/wqy-zenhei.ttc", &config, io->Fonts->GetGlyphRangesChineseFull());

// Load Japanese fonts
addIfExistent(io, "/usr/share/fonts/TTF/takao-mincho.ttf", &config, io->Fonts->GetGlyphRangesJapanese());

// Load Korean fonts
addIfExistent(io, "/usr/share/fonts/TTF/NanumGothic.ttf", &config, io->Fonts->GetGlyphRangesKorean());

// Load Thai fonts
addIfExistent(io, "/usr/share/fonts/TTF/garuda.ttf", &config, io->Fonts->GetGlyphRangesThai());
#endif
// Add the default font as well.
io->Fonts->AddFontDefault(&config);
io->Fonts->Build();
}
} // namespace steppable::gui::__internals
1 change: 1 addition & 0 deletions include/imgui
Submodule imgui added at 469dfd
2 changes: 1 addition & 1 deletion wiki
Submodule wiki updated from b7b130 to 3cde4c

0 comments on commit 779a205

Please sign in to comment.