From 73974250975fa4bbed5e9ef5f2ff46ddd38b5459 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Mar 2015 13:03:46 +0000 Subject: [PATCH] Examples: Refactored directx9_example to be eaasier to copy & paste into user application. --- .../directx9_example/directx9_example.vcxproj | 6 +- .../directx9_example.vcxproj.filters | 6 + examples/directx9_example/imgui_impl_dx9.cpp | 262 ++++++++++++++ examples/directx9_example/imgui_impl_dx9.h | 16 + examples/directx9_example/main.cpp | 340 +++--------------- 5 files changed, 338 insertions(+), 292 deletions(-) create mode 100644 examples/directx9_example/imgui_impl_dx9.cpp create mode 100644 examples/directx9_example/imgui_impl_dx9.h diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index 548f1d3d..3b638b7b 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -48,7 +48,7 @@ Level3 Disabled - $(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) true @@ -63,7 +63,7 @@ MaxSpeed true true - $(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) true @@ -76,11 +76,13 @@ + + diff --git a/examples/directx9_example/directx9_example.vcxproj.filters b/examples/directx9_example/directx9_example.vcxproj.filters index 06afcb03..13e1f412 100644 --- a/examples/directx9_example/directx9_example.vcxproj.filters +++ b/examples/directx9_example/directx9_example.vcxproj.filters @@ -16,6 +16,9 @@ imgui + + sources + @@ -24,5 +27,8 @@ imgui + + sources + \ No newline at end of file diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp new file mode 100644 index 00000000..9e0a342f --- /dev/null +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -0,0 +1,262 @@ +// ImGui Win32 + DirectX9 binding +// https://github.com/ocornut/imgui + +#include +#include "imgui_impl_dx9.h" + +// DirectX +#include +#define DIRECTINPUT_VERSION 0x0800 +#include + +// Data +static INT64 g_Time = 0; +static INT64 g_TicksPerSecond = 0; +static bool g_FontTextureLoaded = false; +static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; +static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; + +struct CUSTOMVERTEX +{ + D3DXVECTOR3 pos; + D3DCOLOR col; + D3DXVECTOR2 uv; +}; +#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) +{ + size_t total_vtx_count = 0; + for (int n = 0; n < cmd_lists_count; n++) + total_vtx_count += cmd_lists[n]->vtx_buffer.size(); + if (total_vtx_count == 0) + return; + + // Copy and convert all vertices into a single contiguous buffer + CUSTOMVERTEX* vtx_dst; + if (g_pVB->Lock(0, (UINT)total_vtx_count, (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) + return; + for (int n = 0; n < cmd_lists_count; n++) + { + const ImDrawList* cmd_list = cmd_lists[n]; + const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0]; + for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++) + { + vtx_dst->pos.x = vtx_src->pos.x; + vtx_dst->pos.y = vtx_src->pos.y; + vtx_dst->pos.z = 0.0f; + vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000)>>16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 + vtx_dst->uv.x = vtx_src->uv.x; + vtx_dst->uv.y = vtx_src->uv.y; + vtx_dst++; + vtx_src++; + } + } + g_pVB->Unlock(); + + g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); + g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); + + // Setup render state: alpha-blending, no face culling, no depth testing + g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); + g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false ); + g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, false ); + g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true ); + g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ); + g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false ); + g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); + g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); + g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, true ); + g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); + g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE ); + g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); + g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); + + // Setup orthographic projection matrix + D3DXMATRIXA16 mat; + D3DXMatrixIdentity(&mat); + g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat); + g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat); + D3DXMatrixOrthoOffCenterLH(&mat, 0.5f, ImGui::GetIO().DisplaySize.x+0.5f, ImGui::GetIO().DisplaySize.y+0.5f, 0.5f, -1.0f, +1.0f); + g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat); + + // Render command lists + int vtx_offset = 0; + for (int n = 0; n < cmd_lists_count; n++) + { + // Render command list + const ImDrawList* cmd_list = cmd_lists[n]; + for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i]; + const RECT r = { (LONG)pcmd->clip_rect.x, (LONG)pcmd->clip_rect.y, (LONG)pcmd->clip_rect.z, (LONG)pcmd->clip_rect.w }; + g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->texture_id ); + g_pd3dDevice->SetScissorRect(&r); + g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, vtx_offset, pcmd->vtx_count/3); + vtx_offset += pcmd->vtx_count; + } + } +} + +LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + ImGuiIO& io = ImGui::GetIO(); + switch (msg) + { + case WM_LBUTTONDOWN: + io.MouseDown[0] = true; + return true; + case WM_LBUTTONUP: + io.MouseDown[0] = false; + return true; + case WM_RBUTTONDOWN: + io.MouseDown[1] = true; + return true; + case WM_RBUTTONUP: + io.MouseDown[1] = false; + return true; + case WM_MOUSEWHEEL: + io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + return true; + case WM_MOUSEMOVE: + io.MousePos.x = (signed short)(lParam); + io.MousePos.y = (signed short)(lParam >> 16); + return true; + case WM_KEYDOWN: + if (wParam >= 0 && wParam < 256) + io.KeysDown[wParam] = 1; + return true; + case WM_KEYUP: + if (wParam >= 0 && wParam < 256) + io.KeysDown[wParam] = 0; + return true; + case WM_CHAR: + // You can also use ToAscii()+GetKeyboardState() to retrieve characters. + if (wParam > 0 && wParam < 0x10000) + io.AddInputCharacter((unsigned short)wParam); + return true; + } + return 0; +} + +void ImGui_ImplDX9_InitFontsTexture() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Build + unsigned char* pixels; + int width, height, bytes_per_pixel; + io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height, &bytes_per_pixel); + + // Create DX9 texture + LPDIRECT3DTEXTURE9 pTexture = NULL; + if (D3DXCreateTexture(g_pd3dDevice, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8, D3DPOOL_DEFAULT, &pTexture) < 0) + { + IM_ASSERT(0); + return; + } + D3DLOCKED_RECT tex_locked_rect; + if (pTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) + { + IM_ASSERT(0); + return; + } + for (int y = 0; y < height; y++) + memcpy((unsigned char *)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel)); + pTexture->UnlockRect(0); + + // Store our identifier + io.Fonts->TexID = (void *)pTexture; + g_FontTextureLoaded = true; +} + +bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device, bool install_callbacks) +{ + g_pd3dDevice = device; + if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) + return false; + if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) + return false; + + // FIXME + RECT rect; + GetClientRect((HWND)hwnd, &rect); + int display_w = (int)(rect.right - rect.left); + int display_h = (int)(rect.bottom - rect.top); + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)display_w, (float)display_h); // Display size, in pixels. For clamping windows positions. + io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime. + io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = VK_UP; + io.KeyMap[ImGuiKey_DownArrow] = VK_UP; + io.KeyMap[ImGuiKey_Home] = VK_HOME; + io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Delete] = VK_DELETE; + io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Enter] = VK_RETURN; + io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; + io.KeyMap[ImGuiKey_A] = 'A'; + io.KeyMap[ImGuiKey_C] = 'C'; + io.KeyMap[ImGuiKey_V] = 'V'; + io.KeyMap[ImGuiKey_X] = 'X'; + io.KeyMap[ImGuiKey_Y] = 'Y'; + io.KeyMap[ImGuiKey_Z] = 'Z'; + + io.RenderDrawListsFn = ImGui_ImplDX9_RenderDrawLists; + io.ImeWindowHandle = hwnd; + + // Create the vertex buffer + if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) + return false; + + return true; +} + +void ImGui_ImplDX9_Shutdown() +{ + if (g_pVB) + { + g_pVB->Release(); + g_pVB = NULL; + } + if (LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)ImGui::GetIO().Fonts->TexID) + { + tex->Release(); + ImGui::GetIO().Fonts->TexID = 0; + } + + ImGui::Shutdown(); +} + +void ImGui_ImplDX9_NewFrame() +{ + if (!g_FontTextureLoaded) + ImGui_ImplDX9_InitFontsTexture(); + + ImGuiIO& io = ImGui::GetIO(); + + // Setup time step + INT64 current_time; + QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); + io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; + g_Time = current_time; + + // Read keyboard modifiers inputs + io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; + io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; + // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events + // io.MousePos : filled by WM_MOUSEMOVE events + // io.MouseDown : filled by WM_*BUTTON* events + // io.MouseWheel : filled by WM_MOUSEWHEEL events + + // Start the frame + ImGui::NewFrame(); +} diff --git a/examples/directx9_example/imgui_impl_dx9.h b/examples/directx9_example/imgui_impl_dx9.h new file mode 100644 index 00000000..327ec25d --- /dev/null +++ b/examples/directx9_example/imgui_impl_dx9.h @@ -0,0 +1,16 @@ +// ImGui Win32 + DirectX9 binding +// https://github.com/ocornut/imgui + +struct IDirect3DDevice9; + +bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device, bool install_callbacks); +void ImGui_ImplDX9_InitFontsTexture(); +void ImGui_ImplDX9_Shutdown(); +void ImGui_ImplDX9_NewFrame(); + +// Handler for Win32 messages, update mouse/keyboard data. +// You may or not need this for your implementation, but it can serve as reference for handling inputs. +// Commented out to avoid dragging dependencies on types. You can copy the extern declaration in your code. +/* +extern LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +*/ diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 4b73328c..6bfd91e7 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -1,112 +1,44 @@ // ImGui - standalone example application for DirectX 9 +// TODO: Allow resizing the application window. #include -#include "../../imgui.h" - -// DirectX 9 +#include +#include "imgui_impl_dx9.h" #include #define DIRECTINPUT_VERSION 0x0800 #include -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strdup - -static HWND hWnd; -static LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice -static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device -static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices -struct CUSTOMVERTEX +extern LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - D3DXVECTOR3 pos; - D3DCOLOR col; - D3DXVECTOR2 uv; -}; -#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) + if (ImGui_ImplDX9_WndProcHandler(hWnd, msg, wParam, lParam)) + return true; -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) -{ - size_t total_vtx_count = 0; - for (int n = 0; n < cmd_lists_count; n++) - total_vtx_count += cmd_lists[n]->vtx_buffer.size(); - if (total_vtx_count == 0) - return; - - // Copy and convert all vertices into a single contiguous buffer - CUSTOMVERTEX* vtx_dst; - if (g_pVB->Lock(0, (UINT)total_vtx_count, (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) - return; - for (int n = 0; n < cmd_lists_count; n++) + switch (msg) { - const ImDrawList* cmd_list = cmd_lists[n]; - const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0]; - for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++) - { - vtx_dst->pos.x = vtx_src->pos.x; - vtx_dst->pos.y = vtx_src->pos.y; - vtx_dst->pos.z = 0.0f; - vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000)>>16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 - vtx_dst->uv.x = vtx_src->uv.x; - vtx_dst->uv.y = vtx_src->uv.y; - vtx_dst++; - vtx_src++; - } - } - g_pVB->Unlock(); - - g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); - g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); - - // Setup render state: alpha-blending, no face culling, no depth testing - g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); - g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false ); - g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, false ); - g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true ); - g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ); - g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false ); - g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); - g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); - g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, true ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); - g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); - g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); - g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); - - // Setup orthographic projection matrix - D3DXMATRIXA16 mat; - D3DXMatrixIdentity(&mat); - g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat); - g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat); - D3DXMatrixOrthoOffCenterLH(&mat, 0.5f, ImGui::GetIO().DisplaySize.x+0.5f, ImGui::GetIO().DisplaySize.y+0.5f, 0.5f, -1.0f, +1.0f); - g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat); - - // Render command lists - int vtx_offset = 0; - for (int n = 0; n < cmd_lists_count; n++) - { - // Render command list - const ImDrawList* cmd_list = cmd_lists[n]; - for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i]; - const RECT r = { (LONG)pcmd->clip_rect.x, (LONG)pcmd->clip_rect.y, (LONG)pcmd->clip_rect.z, (LONG)pcmd->clip_rect.w }; - g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->texture_id ); - g_pd3dDevice->SetScissorRect(&r); - g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, vtx_offset, pcmd->vtx_count/3); - vtx_offset += pcmd->vtx_count; - } + case WM_DESTROY: + PostQuitMessage(0); + return 0; } + return DefWindowProc(hWnd, msg, wParam, lParam); } -HRESULT InitDeviceD3D(HWND hWnd) +int main(int argc, char** argv) { - if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) - return E_FAIL; + // Register the window class + WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL }; + RegisterClassEx(&wc); + // Create the application's window + HWND hwnd = CreateWindow(L"ImGui Example", L"ImGui DirectX9 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); + + // Initialize Direct3D + LPDIRECT3D9 pD3D; + if ((pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) + { + UnregisterClass(L"ImGui Example", wc.hInstance); + return 0; + } D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; @@ -117,207 +49,32 @@ HRESULT InitDeviceD3D(HWND hWnd) d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Create the D3DDevice - if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice) < 0) - return E_FAIL; - - return S_OK; -} - -void CleanupDevice() -{ - // InitImGui - if (g_pVB) g_pVB->Release(); - - // InitDeviceD3D - if (LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)ImGui::GetIO().Fonts->TexID) - tex->Release(); - if (g_pd3dDevice) g_pd3dDevice->Release(); - if (g_pD3D) g_pD3D->Release(); -} - -LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - ImGuiIO& io = ImGui::GetIO(); - switch (msg) + LPDIRECT3DDEVICE9 pd3dDevice = NULL; + if (pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice) < 0) { - case WM_LBUTTONDOWN: - io.MouseDown[0] = true; - return true; - case WM_LBUTTONUP: - io.MouseDown[0] = false; - return true; - case WM_RBUTTONDOWN: - io.MouseDown[1] = true; - return true; - case WM_RBUTTONUP: - io.MouseDown[1] = false; - return true; - case WM_MOUSEWHEEL: - io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; - return true; - case WM_MOUSEMOVE: - // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) - io.MousePos.x = (signed short)(lParam); - io.MousePos.y = (signed short)(lParam >> 16); - return true; - case WM_KEYDOWN: - if (wParam >= 0 && wParam < 256) - io.KeysDown[wParam] = 1; - return true; - case WM_KEYUP: - if (wParam >= 0 && wParam < 256) - io.KeysDown[wParam] = 0; - return true; - case WM_CHAR: - // You can also use ToAscii()+GetKeyboardState() to retrieve characters. - if (wParam > 0 && wParam < 0x10000) - io.AddInputCharacter((unsigned short)wParam); - return true; - case WM_DESTROY: - CleanupDevice(); - PostQuitMessage(0); + pD3D->Release(); + UnregisterClass(L"ImGui Example", wc.hInstance); return 0; } - return DefWindowProc(hWnd, msg, wParam, lParam); -} -void LoadFontsTexture() -{ - // Load one or more font - ImGuiIO& io = ImGui::GetIO(); + ShowWindow(hwnd, SW_SHOWDEFAULT); + UpdateWindow(hwnd); + + // ImGui + ImGui_ImplDX9_Init(hwnd, pd3dDevice, true); + //ImGuiIO& io = ImGui::GetIO(); //ImFont* my_font1 = io.Fonts->AddFontDefault(); //ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("extra_fonts/Karla-Regular.ttf", 15.0f); //ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1; //ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1; //ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese()); - - // Build - unsigned char* pixels; - int width, height, bytes_per_pixel; - io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height, &bytes_per_pixel); - - // Create texture - LPDIRECT3DTEXTURE9 pTexture = NULL; - if (D3DXCreateTexture(g_pd3dDevice, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8, D3DPOOL_DEFAULT, &pTexture) < 0) - { - IM_ASSERT(0); - return; - } - - // Copy pixels - D3DLOCKED_RECT tex_locked_rect; - if (pTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) - { - IM_ASSERT(0); - return; - } - for (int y = 0; y < height; y++) - memcpy((unsigned char *)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel)); - pTexture->UnlockRect(0); - - // Store our identifier - io.Fonts->TexID = (void *)pTexture; -} - -void InitImGui() -{ - RECT rect; - GetClientRect(hWnd, &rect); - int display_w = (int)(rect.right - rect.left); - int display_h = (int)(rect.bottom - rect.top); - - ImGuiIO& io = ImGui::GetIO(); - io.DisplaySize = ImVec2((float)display_w, (float)display_h); // Display size, in pixels. For clamping windows positions. - io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our time step is variable) - io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime. - io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; - io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = VK_UP; - io.KeyMap[ImGuiKey_DownArrow] = VK_UP; - io.KeyMap[ImGuiKey_Home] = VK_HOME; - io.KeyMap[ImGuiKey_End] = VK_END; - io.KeyMap[ImGuiKey_Delete] = VK_DELETE; - io.KeyMap[ImGuiKey_Backspace] = VK_BACK; - io.KeyMap[ImGuiKey_Enter] = VK_RETURN; - io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; - io.KeyMap[ImGuiKey_A] = 'A'; - io.KeyMap[ImGuiKey_C] = 'C'; - io.KeyMap[ImGuiKey_V] = 'V'; - io.KeyMap[ImGuiKey_X] = 'X'; - io.KeyMap[ImGuiKey_Y] = 'Y'; - io.KeyMap[ImGuiKey_Z] = 'Z'; - - io.RenderDrawListsFn = ImImpl_RenderDrawLists; - io.ImeWindowHandle = hWnd; - - // Create the vertex buffer - if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) - { - IM_ASSERT(0); - return; - } - - LoadFontsTexture(); -} - -INT64 ticks_per_second = 0; -INT64 last_time = 0; - -void UpdateImGui() -{ - ImGuiIO& io = ImGui::GetIO(); - - // Setup time step - INT64 current_time; - QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); - io.DeltaTime = (float)(current_time - last_time) / ticks_per_second; - last_time = current_time; - - // Read keyboard modifiers inputs - io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; - io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; - // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events - // io.MousePos : filled by WM_MOUSEMOVE events - // io.MouseDown : filled by WM_*BUTTON* events - // io.MouseWheel : filled by WM_MOUSEWHEEL events - - // Start the frame - ImGui::NewFrame(); -} - -int main(int argc, char** argv) -{ - // Register the window class - WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL }; - RegisterClassEx(&wc); - - // 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); - - if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second)) - return 1; - if (!QueryPerformanceCounter((LARGE_INTEGER *)&last_time)) - return 1; - - // Initialize Direct3D - if (InitDeviceD3D(hWnd) < 0) - { - CleanupDevice(); - UnregisterClass(L"ImGui Example", wc.hInstance); - return 1; - } - - // Show the window - ShowWindow(hWnd, SW_SHOWDEFAULT); - UpdateWindow(hWnd); - - InitImGui(); + ImGui_ImplDX9_InitFontsTexture(); bool show_test_window = true; bool show_another_window = false; ImVec4 clear_col = ImColor(114, 144, 154); - // Enter the message loop + // Main loop MSG msg; ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) @@ -328,7 +85,7 @@ int main(int argc, char** argv) DispatchMessage(&msg); continue; } - UpdateImGui(); + ImGui_ImplDX9_NewFrame(); // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" @@ -358,21 +115,24 @@ int main(int argc, char** argv) } // Rendering - g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); - g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); - g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false); + pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); + pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); + pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false); D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_col.x*255.0f), (int)(clear_col.y*255.0f), (int)(clear_col.z*255.0f), (int)(clear_col.w*255.0f)); - g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0); - if (g_pd3dDevice->BeginScene() >= 0) + pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0); + if (pd3dDevice->BeginScene() >= 0) { ImGui::Render(); - g_pd3dDevice->EndScene(); + pd3dDevice->EndScene(); } - g_pd3dDevice->Present(NULL, NULL, NULL, NULL); + pd3dDevice->Present(NULL, NULL, NULL, NULL); } - ImGui::Shutdown(); + ImGui_ImplDX9_Shutdown(); + if (pd3dDevice) pd3dDevice->Release(); + if (pD3D) pD3D->Release(); UnregisterClass(L"ImGui Example", wc.hInstance); + return 0; }