diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 4af5551d..044c5f69 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -26,7 +26,8 @@ static ID3D10Blob * g_pPixelShaderBlob = NULL; static ID3D11PixelShader* g_pPixelShader = NULL; static ID3D11SamplerState* g_pFontSampler = NULL; static ID3D11ShaderResourceView*g_pFontTextureView = NULL; -static ID3D11BlendState* g_blendState = NULL; +static ID3D11RasterizerState* g_pRasterizerState = NULL; +static ID3D11BlendState* g_pBlendState = NULL; static int VERTEX_BUFFER_SIZE = 30000; // TODO: Make vertex buffer smaller and grow dynamically as needed. struct VERTEX_CONSTANT_BUFFER @@ -100,7 +101,8 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd // Setup render state const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_blendState, blendFactor, 0xffffffff); + g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); + g_pd3dDeviceContext->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -339,19 +341,30 @@ bool ImGui_ImplDX11_CreateDeviceObjects() desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - g_pd3dDevice->CreateBlendState(&desc, &g_blendState); + g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); + } + + // Create the rasterizer state + { + D3D11_RASTERIZER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.FillMode = D3D11_FILL_SOLID; + desc.CullMode = D3D11_CULL_NONE; + desc.ScissorEnable = true; + desc.DepthClipEnable = true; + g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); } // Create the vertex buffer { - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = VERTEX_BUFFER_SIZE * sizeof(ImDrawVert); - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pVB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = VERTEX_BUFFER_SIZE * sizeof(ImDrawVert); + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) return false; } @@ -369,7 +382,8 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() if (g_pFontTextureView) { g_pFontTextureView->Release(); ImGui::GetIO().Fonts->TexID = 0; } if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } - if (g_blendState) { g_blendState->Release(); g_blendState = NULL; } + if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } + if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } diff --git a/imgui.h b/imgui.h index eb982fd6..1aefd98c 100644 --- a/imgui.h +++ b/imgui.h @@ -73,75 +73,8 @@ struct ImVec4 #endif }; -namespace ImGui -{ - // Proxy functions to access the MemAllocFn/MemFreeFn pointers in ImGui::GetIO(). The only reason they exist here is to allow ImVector<> to compile inline. - IMGUI_API void* MemAlloc(size_t sz); - IMGUI_API void MemFree(void* ptr); -} - -// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). -// Use '#define ImVector std::vector' if you want to use the STL type or your own type. -// Our implementation does NOT call c++ constructors because we don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code! -#ifndef ImVector -template -class ImVector -{ -protected: - size_t Size; - size_t Capacity; - T* Data; - -public: - typedef T value_type; - typedef value_type* iterator; - typedef const value_type* const_iterator; - - ImVector() { Size = Capacity = 0; Data = NULL; } - ~ImVector() { if (Data) ImGui::MemFree(Data); } - - inline bool empty() const { return Size == 0; } - inline size_t size() const { return Size; } - inline size_t capacity() const { return Capacity; } - - inline value_type& at(size_t i) { IM_ASSERT(i < Size); return Data[i]; } - inline const value_type& at(size_t i) const { IM_ASSERT(i < Size); return Data[i]; } - inline value_type& operator[](size_t i) { IM_ASSERT(i < Size); return Data[i]; } - inline const value_type& operator[](size_t i) const { IM_ASSERT(i < Size); return Data[i]; } - - inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } } - inline iterator begin() { return Data; } - inline const_iterator begin() const { return Data; } - inline iterator end() { return Data + Size; } - inline const_iterator end() const { return Data + Size; } - inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; } - inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; } - inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size-1]; } - inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size-1]; } - inline void swap(ImVector& rhs) { const size_t rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; const size_t rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } - - inline size_t _grow_capacity(size_t new_size) { size_t new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > new_size ? new_capacity : new_size; } - - inline void resize(size_t new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void reserve(size_t new_capacity) - { - if (new_capacity <= Capacity) return; - T* new_data = (value_type*)ImGui::MemAlloc(new_capacity * sizeof(value_type)); - memcpy(new_data, Data, Size * sizeof(value_type)); - ImGui::MemFree(Data); - Data = new_data; - Capacity = new_capacity; - } - - inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; } - inline void pop_back() { IM_ASSERT(Size > 0); Size--; } - - inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const ptrdiff_t off = it - begin(); memmove(Data + off, Data + off + 1, (Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; } - inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } -}; -#endif // #ifndef ImVector - // Helpers at bottom of the file: +// - class ImVector<> // Lightweight std::vector like class. Use '#define ImVector std::vector' if you want to use the STL type or your own type. // - IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times) // - struct ImGuiTextFilter // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" // - struct ImGuiTextBuffer // Text buffer for logging/accumulating text @@ -432,6 +365,10 @@ namespace ImGui IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); + // Proxy functions to access the MemAllocFn/MemFreeFn pointers in ImGui::GetIO() + IMGUI_API void* MemAlloc(size_t sz); + IMGUI_API void MemFree(void* ptr); + // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself IMGUI_API const char* GetVersion(); IMGUI_API void* GetInternalState(); @@ -741,6 +678,67 @@ struct ImGuiIO // Helpers //----------------------------------------------------------------------------- +// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). +// Use '#define ImVector std::vector' if you want to use the STL type or your own type. +// Our implementation does NOT call c++ constructors because we don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code! +#ifndef ImVector +template +class ImVector +{ +protected: + size_t Size; + size_t Capacity; + T* Data; + +public: + typedef T value_type; + typedef value_type* iterator; + typedef const value_type* const_iterator; + + ImVector() { Size = Capacity = 0; Data = NULL; } + ~ImVector() { if (Data) ImGui::MemFree(Data); } + + inline bool empty() const { return Size == 0; } + inline size_t size() const { return Size; } + inline size_t capacity() const { return Capacity; } + + inline value_type& at(size_t i) { IM_ASSERT(i < Size); return Data[i]; } + inline const value_type& at(size_t i) const { IM_ASSERT(i < Size); return Data[i]; } + inline value_type& operator[](size_t i) { IM_ASSERT(i < Size); return Data[i]; } + inline const value_type& operator[](size_t i) const { IM_ASSERT(i < Size); return Data[i]; } + + inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } } + inline iterator begin() { return Data; } + inline const_iterator begin() const { return Data; } + inline iterator end() { return Data + Size; } + inline const_iterator end() const { return Data + Size; } + inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; } + inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; } + inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size-1]; } + inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size-1]; } + inline void swap(ImVector& rhs) { const size_t rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; const size_t rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } + + inline size_t _grow_capacity(size_t new_size) { size_t new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > new_size ? new_capacity : new_size; } + + inline void resize(size_t new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } + inline void reserve(size_t new_capacity) + { + if (new_capacity <= Capacity) return; + T* new_data = (value_type*)ImGui::MemAlloc(new_capacity * sizeof(value_type)); + memcpy(new_data, Data, Size * sizeof(value_type)); + ImGui::MemFree(Data); + Data = new_data; + Capacity = new_capacity; + } + + inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; } + inline void pop_back() { IM_ASSERT(Size > 0); Size--; } + + inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const ptrdiff_t off = it - begin(); memmove(Data + off, Data + off + 1, (Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; } + inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } +}; +#endif // #ifndef ImVector + // Helper: execute a block of code once a frame only // Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. // Usage: