// Copyright (C) 2019 Nomango #include #include #include #include #include #include #include namespace kiwano { namespace imgui { ImGuiModule::ImGuiModule() { } void ImGuiModule::SetupModule() { // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; // Setup Dear ImGui style ImGui::StyleColorsDark(); window_ = Application::GetInstance().GetMainWindow(); // Setup Platform/Renderer bindings io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) io.BackendPlatformName = "imgui_impl_win32"; io.ImeWindowHandle = window_->GetHandle(); // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during // the application lifetime. io.KeyMap[ImGuiKey_Tab] = (int)KeyCode::Tab; io.KeyMap[ImGuiKey_LeftArrow] = (int)KeyCode::Left; io.KeyMap[ImGuiKey_RightArrow] = (int)KeyCode::Right; io.KeyMap[ImGuiKey_UpArrow] = (int)KeyCode::Up; io.KeyMap[ImGuiKey_DownArrow] = (int)KeyCode::Down; io.KeyMap[ImGuiKey_Delete] = (int)KeyCode::Delete; io.KeyMap[ImGuiKey_Backspace] = (int)KeyCode::Back; io.KeyMap[ImGuiKey_Space] = (int)KeyCode::Space; io.KeyMap[ImGuiKey_Enter] = (int)KeyCode::Enter; io.KeyMap[ImGuiKey_Escape] = (int)KeyCode::Esc; io.KeyMap[ImGuiKey_A] = (int)KeyCode::A; io.KeyMap[ImGuiKey_C] = (int)KeyCode::C; io.KeyMap[ImGuiKey_V] = (int)KeyCode::V; io.KeyMap[ImGuiKey_X] = (int)KeyCode::X; io.KeyMap[ImGuiKey_Y] = (int)KeyCode::Y; io.KeyMap[ImGuiKey_Z] = (int)KeyCode::Z; ImGui_Impl_Init(); } void ImGuiModule::DestroyModule() { ImGui_Impl_Shutdown(); ImGui::DestroyContext(); } void ImGuiModule::OnUpdate(Duration dt) { ImGuiIO& io = ImGui::GetIO(); // Setup time step io.DeltaTime = dt.Seconds(); // Read keyboard modifiers inputs io.KeyCtrl = Input::GetInstance().IsDown(KeyCode::Ctrl); io.KeyShift = Input::GetInstance().IsDown(KeyCode::Shift); io.KeyAlt = Input::GetInstance().IsDown(KeyCode::Alt); io.KeySuper = Input::GetInstance().IsDown(KeyCode::Super); // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below. // Update OS mouse position UpdateMousePos(); // Update OS mouse cursor with the cursor requested by imgui UpdateMouseCursor(); } void ImGuiModule::BeforeRender() { ImGui_Impl_NewFrame(); ImGuiIO& io = ImGui::GetIO(); KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!"); // Setup display size (every frame to accommodate for window resizing) Size display_size = Renderer::GetInstance().GetOutputSize(); io.DisplaySize = ImVec2(display_size.x, display_size.y); ImGui::NewFrame(); } void ImGuiModule::AfterRender() { ImGui::Render(); ImGui_Impl_RenderDrawData(ImGui::GetDrawData()); } void ImGuiModule::HandleEvent(Event* evt) { if (ImGui::GetCurrentContext() == NULL) return; ImGuiIO& io = ImGui::GetIO(); if (evt->IsType()) { if (evt->IsType()) { MouseButton button = dynamic_cast(evt)->button; int index = 0; if (button == MouseButton::Left) index = 0; else if (button == MouseButton::Right) index = 1; else if (button == MouseButton::Middle) index = 2; io.MouseDown[index] = true; } else if (evt->IsType()) { MouseButton button = dynamic_cast(evt)->button; int index = 0; if (button == MouseButton::Left) index = 0; else if (button == MouseButton::Right) index = 1; else if (button == MouseButton::Middle) index = 2; io.MouseDown[index] = false; } else if (evt->IsType()) { float wheel = dynamic_cast(evt)->wheel; io.MouseWheel += wheel; } } else if (evt->IsType()) { if (evt->IsType()) { KeyCode key = dynamic_cast(evt)->code; io.KeysDown[(int)key] = true; } else if (evt->IsType()) { KeyCode key = dynamic_cast(evt)->code; io.KeysDown[(int)key] = false; } else if (evt->IsType()) { // You can also use ToAscii()+GetKeyboardState() to retrieve characters. char ch = dynamic_cast(evt)->value; io.AddInputCharacter(static_cast(ch)); } } } void ImGuiModule::UpdateMousePos() { ImGuiIO& io = ImGui::GetIO(); // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by // user) if (io.WantSetMousePos) { POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; ::ClientToScreen(window_->GetHandle(), &pos); ::SetCursorPos(pos.x, pos.y); } Point pos = Input::GetInstance().GetMousePos(); io.MousePos = ImVec2(pos.x, pos.y); } void ImGuiModule::UpdateMouseCursor() { if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return; static ImGuiMouseCursor last_cursor = ImGuiMouseCursor_None; if (ImGui::GetMouseCursor() == last_cursor) return; last_cursor = ImGui::GetMouseCursor(); CursorType cursor = CursorType::Arrow; switch (last_cursor) { case ImGuiMouseCursor_Arrow: cursor = CursorType::Arrow; break; case ImGuiMouseCursor_TextInput: cursor = CursorType::TextInput; break; case ImGuiMouseCursor_ResizeAll: cursor = CursorType::SizeAll; break; case ImGuiMouseCursor_ResizeEW: cursor = CursorType::SizeWE; break; case ImGuiMouseCursor_ResizeNS: cursor = CursorType::SizeNS; break; case ImGuiMouseCursor_ResizeNESW: cursor = CursorType::SizeNESW; break; case ImGuiMouseCursor_ResizeNWSE: cursor = CursorType::SizeNWSE; break; case ImGuiMouseCursor_Hand: cursor = CursorType::Hand; break; } window_->SetCursor(cursor); } } // namespace imgui } // namespace kiwano