Skip to content

Commit

Permalink
Updated to 1.88 version (current latest)
Browse files Browse the repository at this point in the history
Key features:
   - frame is rendered only when it needs to render
   - reason for frame render is shown in console
   - fixed spurious mouse events resulting in needles updates
   - fixed dpi handling (and made dpi-enabled as default)
  • Loading branch information
sergeyn committed Mar 20, 2022
1 parent 6fae296 commit 7b36bb9
Show file tree
Hide file tree
Showing 9 changed files with 341 additions and 134 deletions.
18 changes: 15 additions & 3 deletions backends/imgui_impl_dx12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ static void ImGui_ImplDX12_CreateFontsTexture()
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();

// clear prior textures if any
SafeRelease(bd->pFontTextureResource);


unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
Expand Down Expand Up @@ -420,7 +425,6 @@ static void ImGui_ImplDX12_CreateFontsTexture()
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, bd->hFontSrvCpuDescHandle);
SafeRelease(bd->pFontTextureResource);
bd->pFontTextureResource = pTexture;
}

Expand Down Expand Up @@ -664,11 +668,17 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
if (result_pipeline_state != S_OK)
return false;

ImGui_ImplDX12_CreateFontsTexture();

return true;
}

void ImGui_ImplDX12_InvalidateFontTexture()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
if (!bd || !bd->pd3dDevice)
return;
SafeRelease(bd->pFontTextureResource);
}

void ImGui_ImplDX12_InvalidateDeviceObjects()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
Expand Down Expand Up @@ -743,4 +753,6 @@ void ImGui_ImplDX12_NewFrame()

if (!bd->pPipelineState)
ImGui_ImplDX12_CreateDeviceObjects();
if (!bd->pFontTextureResource) // texture can be released in case of dpi change
ImGui_ImplDX12_CreateFontsTexture();
}
1 change: 1 addition & 0 deletions backends/imgui_impl_dx12.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame();
IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);

// Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateFontTexture();
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
137 changes: 109 additions & 28 deletions backends/imgui_impl_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,16 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);

struct ImGui_ImplWin32_Data
{
INT64 Time;
INT64 TicksPerSecond;
HWND hWnd;
HWND MouseHwnd;
bool MouseTracked;
int MouseButtonsDown;
INT64 Time;
INT64 TicksPerSecond;
ImGuiMouseCursor LastMouseCursor;
bool HasGamepad;
bool WantUpdateHasGamepad;
int MouseButtonsDown;
int MouseX, MouseY; // against spurious WM_MOUSEMOVE events
ImGuiMouseCursor LastMouseCursor;

#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
HMODULE XInputDLL;
Expand Down Expand Up @@ -129,7 +130,10 @@ bool ImGui_ImplWin32_Init(void* hwnd)
bd->WantUpdateHasGamepad = true;
bd->TicksPerSecond = perf_frequency;
bd->Time = perf_counter;
//bd->LastMouseCursor = ImGuiMouseCursor_Arrow; //windows default is the arrow, no need to reset it
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
bd->MouseX = -1;
bd->MouseY = -1;

// Set platform dependent data in viewport
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)hwnd;
Expand Down Expand Up @@ -180,8 +184,15 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return false;

ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();

ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
if (bd->LastMouseCursor == mouse_cursor)
return false;

bd->LastMouseCursor = mouse_cursor;

if (mouse_cursor == ImGuiMouseCursor_None /*|| io.MouseDrawCursor*/)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
::SetCursor(NULL);
Expand All @@ -190,7 +201,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
{
// Show OS mouse cursor
LPTSTR win32_cursor = IDC_ARROW;
switch (imgui_cursor)
switch (mouse_cursor)
{
case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
Expand Down Expand Up @@ -328,20 +339,59 @@ static void ImGui_ImplWin32_UpdateGamepads()
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
}

void ImGui_ImplWin32_NewFrame()
bool ImGui_ImplWin32_NewFrame(bool poll_only)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWin32_Init()?");

INT64 current_time;




for (;;)
{
::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);

double next_refresh = !poll_only ? io.NextRefresh : 0.0;

double cur_delta = double(current_time - bd->Time) / bd->TicksPerSecond;
if (cur_delta <= next_refresh)
{
double ms_to_wait_double = (next_refresh - cur_delta) * 1000.0f;
unsigned int ms_to_wait = ms_to_wait_double >= MAXDWORD ? INFINITE : unsigned int(ms_to_wait_double);
if (ms_to_wait)
MsgWaitForMultipleObjectsEx(0, nullptr, ms_to_wait, QS_ALLEVENTS, 0);
}


MSG msg;
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
if (msg.message != WM_QUIT)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
continue;
}
return false;
}


if (cur_delta <= next_refresh)
continue;

break;
}


// Setup display size (every frame to accommodate for window resizing)
RECT rect = { 0, 0, 0, 0 };
::GetClientRect(bd->hWnd, &rect);
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));

// Setup time step
INT64 current_time = 0;
::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
bd->Time = current_time;

Expand All @@ -352,15 +402,12 @@ void ImGui_ImplWin32_NewFrame()
ImGui_ImplWin32_ProcessKeyEventsWorkarounds();

// Update OS mouse cursor with the cursor requested by imgui
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
if (bd->LastMouseCursor != mouse_cursor)
{
bd->LastMouseCursor = mouse_cursor;
ImGui_ImplWin32_UpdateMouseCursor();
}

ImGui_ImplWin32_UpdateMouseCursor();

// Update game controllers (if enabled and available)
ImGui_ImplWin32_UpdateGamepads();

return true;
}

// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED, we assign it an arbitrary value to make code more readable (VK_ codes go up to 255)
Expand Down Expand Up @@ -504,33 +551,57 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
if (ImGui::GetCurrentContext() == NULL)
return 0;

const char* key_refresh_reason;
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();

switch (msg)
{
case WM_MOUSEMOVE:

// We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events
if (!bd->MouseHwnd) // mouse entered client area
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;

bd->MouseHwnd = hwnd;
if (!bd->MouseTracked)
{
TRACKMOUSEEVENT tme = { sizeof(tme), TME_LEAVE, hwnd, 0 };
::TrackMouseEvent(&tme);
bd->MouseTracked = true;
}
io.AddMousePosEvent((float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));

{
int m_x = GET_X_LPARAM(lParam), m_y = GET_Y_LPARAM(lParam);
if (bd->MouseX != m_x || bd->MouseY != m_y) // spurious WM_MOUSEMOVE events are a real thing. don't act on them
{
bd->MouseX = m_x, bd->MouseY = m_y;

io.SetNextRefresh(0, "mouse move"); //return 0;

io.AddMousePosEvent((float)m_x, (float)m_y);
}
}
break;
case WM_MOUSELEAVE:
if (bd->MouseHwnd == hwnd)
bd->MouseHwnd = NULL;
bd->MouseTracked = false;
//bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
bd->MouseX = -1, bd->MouseY = -1;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
break;
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
case WM_LBUTTONDOWN: key_refresh_reason = "mouse lbuttonup down"; goto md;
case WM_LBUTTONDBLCLK: key_refresh_reason = "mouse lbuttonup dblclk"; goto md;
case WM_RBUTTONDOWN: key_refresh_reason = "mouse rbuttonup down"; goto md;
case WM_RBUTTONDBLCLK: key_refresh_reason = "mouse rbuttonup dblclk"; goto md;
case WM_MBUTTONDOWN: key_refresh_reason = "mouse mbuttonup donw"; goto md;
case WM_MBUTTONDBLCLK: key_refresh_reason = "mouse mbuttonup dblclk"; goto md;
case WM_XBUTTONDOWN: key_refresh_reason = "mouse xbuttonup down"; goto md;
case WM_XBUTTONDBLCLK: key_refresh_reason = "mouse xbuttonup dblclk";
md:
{
io.SetNextRefresh(0, key_refresh_reason);
int button = 0;
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
Expand All @@ -542,11 +613,13 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
io.AddMouseButtonEvent(button, true);
return 0;
}
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_XBUTTONUP:
case WM_LBUTTONUP: key_refresh_reason = "mouse lbutton up"; goto mu;
case WM_RBUTTONUP:key_refresh_reason = "mouse rbutton up"; goto mu;
case WM_MBUTTONUP:key_refresh_reason = "mouse mbutton up"; goto mu;
case WM_XBUTTONUP:key_refresh_reason = "mouse xbutton up";
mu:
{
io.SetNextRefresh(0, key_refresh_reason);
int button = 0;
if (msg == WM_LBUTTONUP) { button = 0; }
if (msg == WM_RBUTTONUP) { button = 1; }
Expand All @@ -559,19 +632,27 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
return 0;
}
case WM_MOUSEWHEEL:
io.SetNextRefresh(0, "wheel up");
io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
return 0;
case WM_MOUSEHWHEEL:
io.SetNextRefresh(0, "wheel down");
io.AddMouseWheelEvent((float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f);
return 0;
case WM_KEYDOWN:
key_refresh_reason = "key down"; goto l;
case WM_KEYUP:
key_refresh_reason = "key up"; goto l;
case WM_SYSKEYDOWN:
key_refresh_reason = "syskey down"; goto l;
case WM_SYSKEYUP:
{
const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
key_refresh_reason = "key up";
l:
{
const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
if (wParam < 256)
{
io.SetNextRefresh(0, key_refresh_reason);
// Submit modifiers
ImGui_ImplWin32_UpdateKeyModifiers();

Expand Down
2 changes: 1 addition & 1 deletion backends/imgui_impl_win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplWin32_NewFrame(bool poll = false);

// Win32 message handler your application need to call.
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
Expand Down
Loading

0 comments on commit 7b36bb9

Please sign in to comment.