#include "imgui_backend.hpp" #include #include #include "engine.hpp" #include "platform.hpp" #include "assertions.hpp" #include "input.hpp" #include "app.hpp" using prism::imgui_backend; const std::map imToPl = { {ImGuiKey_Tab, InputButton::Tab}, {ImGuiKey_LeftArrow, InputButton::LeftArrow}, {ImGuiKey_RightArrow, InputButton::RightArrow}, {ImGuiKey_UpArrow, InputButton::Escape}, {ImGuiKey_DownArrow, InputButton::Escape}, {ImGuiKey_PageUp, InputButton::Escape}, {ImGuiKey_PageDown, InputButton::Escape}, {ImGuiKey_Home, InputButton::Escape}, {ImGuiKey_End, InputButton::Escape}, {ImGuiKey_Insert, InputButton::Escape}, {ImGuiKey_Delete, InputButton::Escape}, {ImGuiKey_Backspace, InputButton::Backspace}, {ImGuiKey_Space, InputButton::Space}, {ImGuiKey_Enter, InputButton::Enter}, {ImGuiKey_Escape, InputButton::Escape}, {ImGuiKey_A, InputButton::A}, {ImGuiKey_C, InputButton::C}, {ImGuiKey_V, InputButton::V}, {ImGuiKey_X, InputButton::X}, {ImGuiKey_Y, InputButton::Y}, {ImGuiKey_Z, InputButton::Z} }; imgui_backend::imgui_backend() { ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); io.IniFilename = ""; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; io.BackendPlatformName = "Prism"; for (auto& [im, pl] : imToPl) io.KeyMap[im] = platform::get_keycode(pl); const auto theme = platform::get_theme(); switch(theme) { case PlatformTheme::Light: ImGui::StyleColorsLight(); break; case PlatformTheme::Dark: { ImGui::StyleColorsDark(); auto& style = ImGui::GetStyle(); style.FrameRounding = 3; style.FrameBorderSize = 0.0f; style.WindowBorderSize = 0.0f; style.WindowPadding = ImVec2(10, 10); style.FramePadding = ImVec2(4, 4); style.ItemInnerSpacing = ImVec2(5, 0); style.ItemSpacing = ImVec2(10, 5); style.ScrollbarSize = 10; style.GrabMinSize = 6; style.WindowRounding = 3.0f; style.ChildRounding = 3.0f; style.PopupRounding = 3.0f; style.ScrollbarRounding = 12.0f; style.GrabRounding = 3.0f; style.TabRounding = 3.0f; style.WindowTitleAlign = ImVec2(0.0, 0.5); ImVec4* colors = ImGui::GetStyle().Colors; colors[ImGuiCol_FrameBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.54f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.68f, 0.68f, 0.68f, 0.40f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.47f, 0.52f, 0.67f); colors[ImGuiCol_TitleBgActive] = ImVec4(0.23f, 0.43f, 0.73f, 1.00f); colors[ImGuiCol_CheckMark] = ImVec4(0.74f, 0.80f, 0.87f, 1.00f); colors[ImGuiCol_SliderGrab] = ImVec4(0.46f, 0.54f, 0.64f, 1.00f); colors[ImGuiCol_Button] = ImVec4(0.38f, 0.51f, 0.65f, 0.40f); colors[ImGuiCol_ButtonHovered] = ImVec4(0.57f, 0.61f, 0.67f, 1.00f); colors[ImGuiCol_ButtonActive] = ImVec4(0.32f, 0.34f, 0.36f, 1.00f); colors[ImGuiCol_Tab] = ImVec4(0.22f, 0.27f, 0.33f, 0.86f); colors[ImGuiCol_TabActive] = ImVec4(0.33f, 0.51f, 0.75f, 1.00f); colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.30f, 0.33f, 0.38f, 1.00f); } break; } ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformMonitor monitor = {}; const auto monitorArea = platform::get_monitor_resolution(); monitor.MainPos = monitorArea.offset; monitor.MainSize = monitorArea.extent; const auto workArea = platform::get_monitor_work_area(); monitor.WorkPos = workArea.offset; monitor.WorkSize = workArea.extent; monitor.DpiScale = platform::get_monitor_dpi(); platform_io.Monitors.push_back(monitor); platform_io.Platform_CreateWindow = [](ImGuiViewport* viewport) { viewport->PlatformHandle = platform::open_window("", {viewport->Pos, viewport->Size}, WindowFlags::Borderless); }; platform_io.Platform_DestroyWindow = [](ImGuiViewport* viewport) { platform::close_window(viewport->PlatformHandle); }; platform_io.Platform_ShowWindow = [](ImGuiViewport*) {}; platform_io.Platform_SetWindowPos = [](ImGuiViewport* viewport, const ImVec2 pos) { platform::set_window_position(viewport->PlatformHandle, pos); }; platform_io.Platform_GetWindowPos = [](ImGuiViewport* viewport) -> ImVec2 { return platform::get_window_position(viewport->PlatformHandle); }; platform_io.Platform_SetWindowSize = [](ImGuiViewport* viewport, const ImVec2 size) { platform::set_window_size(viewport->PlatformHandle, size); ::engine->resize(viewport->PlatformHandle, size); }; platform_io.Platform_GetWindowSize = [](ImGuiViewport* viewport) -> ImVec2 { return platform::get_window_size(viewport->PlatformHandle); }; platform_io.Platform_SetWindowFocus = [](ImGuiViewport* viewport) { platform::set_window_focused(viewport->PlatformHandle); }; platform_io.Platform_GetWindowFocus = [](ImGuiViewport* viewport) { return platform::is_window_focused(viewport->PlatformHandle); }; platform_io.Platform_GetWindowMinimized = [](ImGuiViewport*) { return false; }; platform_io.Platform_SetWindowTitle = [](ImGuiViewport* viewport, const char* title) { platform::set_window_title(viewport->PlatformHandle, title); }; } void imgui_backend::process_move(platform::window_ptr identifier) { auto viewport = ImGui::FindViewportByPlatformHandle(identifier); if(viewport != nullptr) viewport->PlatformRequestMove = true; } void imgui_backend::process_resize(platform::window_ptr identifier) { auto viewport = ImGui::FindViewportByPlatformHandle(identifier); if(viewport != nullptr) viewport->PlatformRequestResize = true; } void imgui_backend::begin_frame(const float delta_time) { ImGuiIO& io = ImGui::GetIO(); const bool imgui_wants_text = io.WantTextInput; const bool input_is_text = ::engine->get_input()->is_text_input(); if(imgui_wants_text != input_is_text) { if(imgui_wants_text) { ::engine->get_input()->begin_text_input(); } else { ::engine->get_input()->end_text_input(); } } const auto size = platform::get_window_size(::engine->get_main_window()); const auto drawableSize = platform::get_window_drawable_size(::engine->get_main_window()); io.DisplaySize = size; io.DisplayFramebufferScale = ImVec2(static_cast(drawableSize.width) / static_cast(size.width), static_cast(drawableSize.height) / static_cast(size.height)); io.DeltaTime = delta_time; io.KeyCtrl = platform::get_key_down(InputButton::Ctrl); io.KeyShift = platform::get_key_down(InputButton::Shift); io.KeyAlt = platform::get_key_down(InputButton::Alt); io.KeySuper = platform::get_key_down(InputButton::Super); io.MouseHoveredViewport = 0; const auto [sx, sy] = platform::get_wheel_delta(); io.MouseWheel = sy; io.MouseWheelH = sx; if(io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { const auto [x, y] = platform::get_screen_cursor_position(); io.MousePos = ImVec2(static_cast(x), static_cast(y)); } else { const auto [x, y] = platform::get_cursor_position(); io.MousePos = ImVec2(static_cast(x), static_cast(y)); } io.MouseDown[0] = mouse_buttons[0] || platform::get_mouse_button_down(0); // left io.MouseDown[1] = mouse_buttons[1] || platform::get_mouse_button_down(1); // right io.MouseDown[2] = mouse_buttons[2] || platform::get_mouse_button_down(2); // middle mouse_buttons[0] = mouse_buttons[1] = mouse_buttons[2] = false; ImGui::NewFrame(); if(open_dialog_next_frame) { ImGui::OpenPopup("Open File"); open_dialog_next_frame = false; } if(save_dialog_next_frame) { ImGui::OpenPopup("Save File"); save_dialog_next_frame = false; } const auto dialog_function = [](dialog_data& data) { if(ImGui::Selectable("..", false, ImGuiSelectableFlags_DontClosePopups)) data.current_path = data.current_path.parent_path(); for(auto dir_ent : std::filesystem::directory_iterator(data.current_path)) { if(ImGui::Selectable(dir_ent.path().c_str(), data.selected_path == dir_ent.path(), ImGuiSelectableFlags_DontClosePopups)) { if(dir_ent.is_directory()) data.current_path = dir_ent.path(); else data.selected_path = dir_ent.path(); } } ImGui::TextDisabled("Selected: %s", data.selected_path.c_str()); if(ImGui::Button("OK")) { data.return_function(data.selected_path.string()); ImGui::CloseCurrentPopup(); } if(ImGui::Button("Cancel")) ImGui::CloseCurrentPopup(); }; if(ImGui::BeginPopup("Open File")) { dialog_function(open_dialog_data); ImGui::EndPopup(); } if(ImGui::BeginPopup("Save File")) { dialog_function(save_dialog_data); ImGui::EndPopup(); } ImGui::ShowMetricsWindow(); } void imgui_backend::render() { ImGui::EndFrame(); ImGui::Render(); } void imgui_backend::process_key_down(unsigned int key_code) { Expects(key_code >= 0); ImGuiIO& io = ImGui::GetIO(); io.KeysDown[key_code] = true; } void imgui_backend::process_key_up(unsigned int key_code) { Expects(key_code >= 0); ImGuiIO& io = ImGui::GetIO(); io.KeysDown[key_code] = false; } void imgui_backend::process_mouse_down(int button) { mouse_buttons[button] = true; } void prism::imgui_backend::process_text_input(const std::string_view string) { ImGuiIO& io = ImGui::GetIO(); io.AddInputCharactersUTF8(string.data()); } void prism::imgui_backend::open_dialog(const bool existing, std::function returnFunction, bool openDirectory) { open_dialog_next_frame = true; open_dialog_data.current_path = std::filesystem::current_path(); open_dialog_data.return_function = returnFunction; } void prism::imgui_backend::save_dialog(std::function returnFunction) { save_dialog_next_frame = true; save_dialog_data.current_path = std::filesystem::current_path(); save_dialog_data.return_function = returnFunction; }