diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 0b09c82c..3036eb75 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -220,6 +220,35 @@ void InitImGui() } } +INT64 ticks_per_second = 0; +INT64 time = 0; + +void UpdateImGui() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup timestep + INT64 current_time; + QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); + io.DeltaTime = (float)(current_time - time) / ticks_per_second; + time = current_time; + + // Setup inputs + // (we already got mouse position, buttons, wheel from the window message callback) + BYTE keystate[256]; + GetKeyboardState(keystate); + for (int i = 0; i < 256; i++) + io.KeysDown[i] = (keystate[i] & 0x80) != 0; + io.KeyCtrl = (keystate[VK_CONTROL] & 0x80) != 0; + io.KeyShift = (keystate[VK_SHIFT] & 0x80) != 0; + // io.MousePos : filled by WM_MOUSEMOVE event + // io.MouseDown : filled by WM_*BUTTON* events + // io.MouseWheel : filled by WM_MOUSEWHEEL events + + // Start the frame + ImGui::NewFrame(); +} + int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int) { // Register the window class @@ -229,101 +258,91 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int) // Create the application's window hWnd = CreateWindow(L"ImGui Example", L"ImGui DirectX9 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); - INT64 ticks_per_second, time; if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second)) return 1; if (!QueryPerformanceCounter((LARGE_INTEGER *)&time)) return 1; // Initialize Direct3D - if (InitD3D(hWnd) >= 0) + if (InitD3D(hWnd) < 0) + { + if (g_pVB) + g_pVB->Release(); + UnregisterClass(L"ImGui Example", wc.hInstance); + return 1; + } + + // Show the window + ShowWindow(hWnd, SW_SHOWDEFAULT); + UpdateWindow(hWnd); + + InitImGui(); + + // Enter the message loop + MSG msg; + ZeroMemory(&msg, sizeof(msg)); + while (msg.message != WM_QUIT) { - // Show the window - ShowWindow(hWnd, SW_SHOWDEFAULT); - UpdateWindow(hWnd); - - InitImGui(); - - // Enter the message loop - MSG msg; - ZeroMemory(&msg, sizeof(msg)); - while (msg.message != WM_QUIT) + if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { - if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - continue; - } + TranslateMessage(&msg); + DispatchMessage(&msg); + continue; + } - // 1) ImGui start frame, setup time delta & inputs - ImGuiIO& io = ImGui::GetIO(); - INT64 current_time; - QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); - io.DeltaTime = (float)(current_time - time) / ticks_per_second; - time = current_time; - BYTE keystate[256]; - GetKeyboardState(keystate); - for (int i = 0; i < 256; i++) - io.KeysDown[i] = (keystate[i] & 0x80) != 0; - io.KeyCtrl = (keystate[VK_CONTROL] & 0x80) != 0; - io.KeyShift = (keystate[VK_SHIFT] & 0x80) != 0; - // io.MousePos : filled by WM_MOUSEMOVE event - // io.MouseDown : filled by WM_*BUTTON* events - // io.MouseWheel : filled by WM_MOUSEWHEEL events - ImGui::NewFrame(); + UpdateImGui(); - // 2) ImGui usage - static bool show_test_window = true; - static bool show_another_window = false; - static float f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - show_test_window ^= ImGui::Button("Test Window"); - show_another_window ^= ImGui::Button("Another Window"); + // Create a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + static bool show_test_window = true; + static bool show_another_window = false; + static float f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + show_test_window ^= ImGui::Button("Test Window"); + show_another_window ^= ImGui::Button("Another Window"); - // Calculate and show framerate - static float ms_per_frame[120] = { 0 }; - static int ms_per_frame_idx = 0; - static float ms_per_frame_accum = 0.0f; - ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx]; - ms_per_frame[ms_per_frame_idx] = io.DeltaTime * 1000.0f; - ms_per_frame_accum += ms_per_frame[ms_per_frame_idx]; - ms_per_frame_idx = (ms_per_frame_idx + 1) % 120; - const float ms_per_frame_avg = ms_per_frame_accum / 120; - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg); + // Calculate and show framerate + static float ms_per_frame[120] = { 0 }; + static int ms_per_frame_idx = 0; + static float ms_per_frame_accum = 0.0f; + ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx]; + ms_per_frame[ms_per_frame_idx] = ImGui::GetIO().DeltaTime * 1000.0f; + ms_per_frame_accum += ms_per_frame[ms_per_frame_idx]; + ms_per_frame_idx = (ms_per_frame_idx + 1) % 120; + const float ms_per_frame_avg = ms_per_frame_accum / 120; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg); - if (show_test_window) - { - // More example code in ShowTestWindow() - ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! - ImGui::ShowTestWindow(&show_test_window); - } - - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100)); - ImGui::Text("Hello"); - ImGui::End(); - } - - // 3) Rendering - // Clear frame buffer - g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); - g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); - g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false); - g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0); - if (g_pd3dDevice->BeginScene() >= 0) - { - // Render ImGui - ImGui::Render(); - g_pd3dDevice->EndScene(); - } - g_pd3dDevice->Present(NULL, NULL, NULL, NULL); + // Show the ImGui test window + // Most of user example code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! + ImGui::ShowTestWindow(&show_test_window); } - ImGui::Shutdown(); - } + // Show another simple window + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100)); + ImGui::Text("Hello"); + ImGui::End(); + } + + // Rendering + g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); + g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); + g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false); + g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0); + if (g_pd3dDevice->BeginScene() >= 0) + { + ImGui::Render(); + g_pd3dDevice->EndScene(); + } + g_pd3dDevice->Present(NULL, NULL, NULL, NULL); + } + + ImGui::Shutdown(); if (g_pVB) g_pVB->Release(); diff --git a/examples/opengl_example/main.cpp b/examples/opengl_example/main.cpp index c26f6cf6..609021ea 100644 --- a/examples/opengl_example/main.cpp +++ b/examples/opengl_example/main.cpp @@ -19,7 +19,7 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c if (cmd_lists_count == 0) return; - // Setup render state: alpha-blending enabled, no face culling, no depth testing + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); @@ -29,11 +29,11 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - // Bind texture + // Setup texture glBindTexture(GL_TEXTURE_2D, fontTex); glEnable(GL_TEXTURE_2D); - // Setup matrices + // Setup orthographic projection matrix const float width = ImGui::GetIO().DisplaySize.x; const float height = ImGui::GetIO().DisplaySize.y; glMatrixMode(GL_PROJECTION); @@ -73,24 +73,33 @@ static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end) if (!text_end) text_end = text + strlen(text); - // Add a zero-terminator because glfw function doesn't take a size - char* buf = (char*)malloc(text_end - text + 1); - memcpy(buf, text, text_end-text); - buf[text_end-text] = '\0'; - glfwSetClipboardString(window, buf); - free(buf); + if (*text_end == 0) + { + // Already got a zero-terminator at 'text_end', we don't need to add one + glfwSetClipboardString(window, text); + } + else + { + // Add a zero-terminator because glfw function doesn't take a size + char* buf = (char*)malloc(text_end - text + 1); + memcpy(buf, text, text_end-text); + buf[text_end-text] = '\0'; + glfwSetClipboardString(window, buf); + free(buf); + } } + // GLFW callbacks to get events static void glfw_error_callback(int error, const char* description) { fputs(description, stderr); } -static float mouse_wheel = 0.0f; static void glfw_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { - mouse_wheel = (float)yoffset; + ImGuiIO& io = ImGui::GetIO(); + io.MouseWheel = (yoffset != 0.0f) ? yoffset > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1 } static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) @@ -173,37 +182,43 @@ void InitImGui() stbi_image_free(tex_data); } -void Shutdown() +void UpdateImGui() { - ImGui::Shutdown(); - glfwTerminate(); + ImGuiIO& io = ImGui::GetIO(); + + // Setup timestep + static double time = 0.0f; + const double current_time = glfwGetTime(); + io.DeltaTime = (float)(current_time - time); + time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + double mouse_x, mouse_y; + glfwGetCursorPos(window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + io.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0; + io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0; + + // Start the frame + ImGui::NewFrame(); } +// Application code int main(int argc, char** argv) { InitGL(); InitImGui(); - double time = glfwGetTime(); while (!glfwWindowShouldClose(window)) { ImGuiIO& io = ImGui::GetIO(); + io.MouseWheel = 0; glfwPollEvents(); + UpdateImGui(); - // 1) ImGui start frame, setup time delta & inputs - const double current_time = glfwGetTime(); - io.DeltaTime = (float)(current_time - time); - time = current_time; - double mouse_x, mouse_y; - glfwGetCursorPos(window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) - io.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0; - io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0; - io.MouseWheel = (mouse_wheel != 0) ? mouse_wheel > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1 - mouse_wheel = 0.0f; - ImGui::NewFrame(); - - // 2) ImGui usage + // Create a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" static bool show_test_window = true; static bool show_another_window = false; static float f; @@ -217,19 +232,21 @@ int main(int argc, char** argv) static int ms_per_frame_idx = 0; static float ms_per_frame_accum = 0.0f; ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx]; - ms_per_frame[ms_per_frame_idx] = io.DeltaTime * 1000.0f; + ms_per_frame[ms_per_frame_idx] = ImGui::GetIO().DeltaTime * 1000.0f; ms_per_frame_accum += ms_per_frame[ms_per_frame_idx]; ms_per_frame_idx = (ms_per_frame_idx + 1) % 120; const float ms_per_frame_avg = ms_per_frame_accum / 120; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg); + // Show the ImGui test window + // Most of user example code is in ImGui::ShowTestWindow() if (show_test_window) { - // More example code in ShowTestWindow() ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowTestWindow(&show_test_window); } + // Show another simple window if (show_another_window) { ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100)); @@ -237,15 +254,15 @@ int main(int argc, char** argv) ImGui::End(); } - // 3) Rendering + // Rendering glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); glClearColor(0.8f, 0.6f, 0.6f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ImGui::Render(); - glfwSwapBuffers(window); } - Shutdown(); + ImGui::Shutdown(); + glfwTerminate(); return 0; }