diff --git a/.gitignore b/.gitignore index 880ac59..c3c6262 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ build/ +_codeql_build_dir/ +_codeql_detected_source_root .DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bd110f..e0034f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,13 @@ FetchContent_Declare( GIT_TAG v1.91.9b ) -FetchContent_MakeAvailable(glfw imgui) +FetchContent_Declare( + stb + GIT_REPOSITORY https://github.com/nothings/stb.git + GIT_TAG f1c79c0 +) + +FetchContent_MakeAvailable(glfw imgui stb) add_library(imgui STATIC ${imgui_SOURCE_DIR}/imgui.cpp @@ -121,7 +127,7 @@ add_executable(${DIRECTOR_EXE_NAME} src/platform_process_windows.cpp ) -target_include_directories(${DIRECTOR_EXE_NAME} PRIVATE src) +target_include_directories(${DIRECTOR_EXE_NAME} PRIVATE src ${stb_SOURCE_DIR}) find_package(OpenGL REQUIRED) diff --git a/src/gui_app.cpp b/src/gui_app.cpp index 048702d..0ee14ab 100644 --- a/src/gui_app.cpp +++ b/src/gui_app.cpp @@ -9,11 +9,15 @@ #include +#define STB_IMAGE_IMPLEMENTATION +#include + #include #include #include #include #include +#include #include #include @@ -232,9 +236,6 @@ std::string compose_plain_log_text(const ProcessRuntimeView& view) { } // namespace int GuiApp::run(ProcessManager* manager, const std::string& executable_path, const std::string& config_path) { -#ifdef _WIN32 - (void)executable_path; -#endif if (!glfwInit()) { return 1; } @@ -274,6 +275,35 @@ int GuiApp::run(ProcessManager* manager, const std::string& executable_path, con ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version); + // Load logo from ../share/images/logo_white.png relative to the executable + GLuint logo_texture = 0; + float logo_display_w = 0.0f; + float logo_display_h = 0.0f; + { + const std::filesystem::path exe_path(executable_path); + std::filesystem::path logo_path; + if (exe_path.has_parent_path()) { + logo_path = exe_path.parent_path() / ".." / "share" / "images" / "logo_white.png"; + } else { + logo_path = std::filesystem::path("..") / "share" / "images" / "logo_white.png"; + } + int w = 0, h = 0, channels = 0; + unsigned char* data = stbi_load(logo_path.string().c_str(), &w, &h, &channels, 4); + if (data != nullptr) { + const float max_h = 30.0f; + const float scale = max_h / static_cast(h); + logo_display_w = static_cast(w) * scale; + logo_display_h = max_h; + glGenTextures(1, &logo_texture); + glBindTexture(GL_TEXTURE_2D, logo_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_2D, 0); + stbi_image_free(data); + } + } + std::size_t selected = 0; std::string status_line; std::vector send_buffers; @@ -515,11 +545,19 @@ int GuiApp::run(ProcessManager* manager, const std::string& executable_path, con ImGui::Columns(1); ImGui::EndChild(); ImGui::Separator(); + if (logo_texture != 0) { + ImGui::Image(static_cast(logo_texture), ImVec2(logo_display_w, logo_display_h)); + ImGui::SameLine(); + ImGui::BeginGroup(); + } ImGui::Text("Status: %s", status_line.empty() ? "ready" : status_line.c_str()); const auto* selected_view = manager->process_at(selected); ImGui::TextWrapped("Command: %s", (selected_view == nullptr || selected_view->command.empty()) ? "" : selected_view->command.c_str()); + if (logo_texture != 0) { + ImGui::EndGroup(); + } ImGui::End(); @@ -537,6 +575,10 @@ int GuiApp::run(ProcessManager* manager, const std::string& executable_path, con manager->stop_all(); + if (logo_texture != 0) { + glDeleteTextures(1, &logo_texture); + } + ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext();